List Every Number That Appears Twice
Solve this Problemnums of length n where every value is between 1 and n, and each value appears either once or twice, return every value that appears twice.
The array's own values are secretly valid indices into itself — that's the constraint a brute-force scan throws away. Treat each value as a pointer to a slot, and flip the sign of what's stored there the first time you visit it. A negative sign IS the "already seen" flag, so a second visit to the same slot is instantly recognizable — no hash setHash SetA collection that lets you check "have I seen this value before?" in O(1) time, normally backed by extra memory. This problem's constraints let the input array itself play that role. required, and the whole scan finishes in a single O(n) pass.
Test Case 1:
Test Case 2:
Test Case 3:
Constraints
- ◆
1 ≤ n = nums.length ≤ 10⁵ - ◆
1 ≤ nums[i] ≤ n - ◆
Each integer appears once or twice — never more
Try the Dry Run
Don't just read the solution — watch it execute, one step at a time.
| 1 | class Solution { |
| 2 | public int[] findAllDuplicates(int[] nums) { |
| 3 | List<Integer> result = new ArrayList<>(); |
| 4 | for (int i = 0; i < nums.length; i++) { |
| 5 | int index = Math.abs(nums[i]) - 1; |
| 6 | if (nums[index] < 0) { |
| 7 | result.add(index + 1); |
| 8 | } else { |
| 9 | nums[index] = -nums[index]; |
| 10 | } |
| 11 | } |
| 12 | int[] arr = new int[result.size()]; |
| 13 | for (int i = 0; i < arr.length; i++) arr[i] = result.get(i); |
| 14 | return arr; |
| 15 | } |
| 16 | } |
| 17 |
[]Start with an empty result. We'll reuse the array itself to remember which values we've already seen, by flipping their sign.
Approach & Solutions
Brute Force
BruteFor every value, rescan the whole array to count how many times it appears. If it appears exactly twice and hasn't already been recorded, add it to the result. Correct, but re-counting from scratch for every position wastes the fact that the array only needs a single pass to answer this.
O(n²)O(1) extra1class Solution {
2 public int[] findAllDuplicates(int[] nums) {
3 List<Integer> result = new ArrayList<>();
4 for (int i = 0; i < nums.length; i++) {
5 int count = 0;
6 for (int j = 0; j < nums.length; j++) {
7 if (nums[j] == nums[i]) count++;
8 }
9 if (count == 2 && !result.contains(nums[i])) {
10 result.add(nums[i]);
11 }
12 }
13 int[] arr = new int[result.size()];
14 for (int i = 0; i < arr.length; i++) arr[i] = result.get(i);
15 return arr;
16 }
17}Optimal — Negative Marking In-Place
OptimalEvery value in this array is guaranteed to be a valid 1-based index into the same array — that constraint is the key to an O(1)-space trick. Walk the array once: for each value, look at the slot it points to (its absolute value minus one). If that slot's number is already negative, this value has been seen before — it's a duplicate. Otherwise, negate the number in that slot to mark "seen." The array's own sign bits become the hash set, with no extra memory needed.
O(n)O(1) extra1class Solution {
2 public int[] findAllDuplicates(int[] nums) {
3 List<Integer> result = new ArrayList<>();
4 for (int i = 0; i < nums.length; i++) {
5 int index = Math.abs(nums[i]) - 1;
6 if (nums[index] < 0) {
7 result.add(index + 1);
8 } else {
9 nums[index] = -nums[index];
10 }
11 }
12 int[] arr = new int[result.size()];
13 for (int i = 0; i < arr.length; i++) arr[i] = result.get(i);
14 return arr;
15 }
16}