Skip to content

Commit fb55881

Browse files
feat: add Single Number III solution
- Bit manipulation algorithm implementation - Multiple approaches: Hash Map, Sorting, Recursive, Mathematical - O(n) time, O(1) space complexity - Comprehensive solutions and optimizations
1 parent 29d997b commit fb55881

File tree

1 file changed

+228
-0
lines changed

1 file changed

+228
-0
lines changed
Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
/**
2+
* Time Complexity: O(n) - Two passes
3+
* Space Complexity: O(1) - No extra space
4+
*/
5+
class Solution {
6+
public int[] singleNumber(int[] nums) {
7+
int xor = 0;
8+
9+
// XOR all elements to get XOR of two single numbers
10+
for (int num : nums) {
11+
xor ^= num;
12+
}
13+
14+
// Find rightmost set bit
15+
int rightmostSetBit = xor & (-xor);
16+
17+
int num1 = 0, num2 = 0;
18+
19+
// Partition array based on rightmost set bit
20+
for (int num : nums) {
21+
if ((num & rightmostSetBit) == 0) {
22+
num1 ^= num;
23+
} else {
24+
num2 ^= num;
25+
}
26+
}
27+
28+
return new int[]{num1, num2};
29+
}
30+
}
31+
32+
// Alternative approach using hash map
33+
class SolutionHashMap {
34+
public int[] singleNumber(int[] nums) {
35+
Map<Integer, Integer> count = new HashMap<>();
36+
37+
for (int num : nums) {
38+
count.put(num, count.getOrDefault(num, 0) + 1);
39+
}
40+
41+
int[] result = new int[2];
42+
int index = 0;
43+
44+
for (Map.Entry<Integer, Integer> entry : count.entrySet()) {
45+
if (entry.getValue() == 1) {
46+
result[index++] = entry.getKey();
47+
}
48+
}
49+
50+
return result;
51+
}
52+
}
53+
54+
// Alternative approach using sorting
55+
class SolutionSorting {
56+
public int[] singleNumber(int[] nums) {
57+
Arrays.sort(nums);
58+
int[] result = new int[2];
59+
int index = 0;
60+
61+
for (int i = 0; i < nums.length; i++) {
62+
if (i == nums.length - 1 || nums[i] != nums[i + 1]) {
63+
result[index++] = nums[i];
64+
} else {
65+
i++; // Skip the next element
66+
}
67+
}
68+
69+
return result;
70+
}
71+
}
72+
73+
// Alternative approach using iterative
74+
class SolutionIterative {
75+
public int[] singleNumber(int[] nums) {
76+
int xor = 0;
77+
78+
for (int i = 0; i < nums.length; i++) {
79+
xor ^= nums[i];
80+
}
81+
82+
int rightmostSetBit = xor & (-xor);
83+
int num1 = 0, num2 = 0;
84+
85+
for (int i = 0; i < nums.length; i++) {
86+
if ((nums[i] & rightmostSetBit) == 0) {
87+
num1 ^= nums[i];
88+
} else {
89+
num2 ^= nums[i];
90+
}
91+
}
92+
93+
return new int[]{num1, num2};
94+
}
95+
}
96+
97+
// Alternative approach using while loop
98+
class SolutionWhileLoop {
99+
public int[] singleNumber(int[] nums) {
100+
int xor = 0;
101+
int i = 0;
102+
103+
while (i < nums.length) {
104+
xor ^= nums[i];
105+
i++;
106+
}
107+
108+
int rightmostSetBit = xor & (-xor);
109+
int num1 = 0, num2 = 0;
110+
i = 0;
111+
112+
while (i < nums.length) {
113+
if ((nums[i] & rightmostSetBit) == 0) {
114+
num1 ^= nums[i];
115+
} else {
116+
num2 ^= nums[i];
117+
}
118+
i++;
119+
}
120+
121+
return new int[]{num1, num2};
122+
}
123+
}
124+
125+
// Alternative approach using enhanced for loop
126+
class SolutionEnhancedForLoop {
127+
public int[] singleNumber(int[] nums) {
128+
int xor = 0;
129+
130+
for (int num : nums) {
131+
xor ^= num;
132+
}
133+
134+
int rightmostSetBit = xor & (-xor);
135+
int num1 = 0, num2 = 0;
136+
137+
for (int num : nums) {
138+
if ((num & rightmostSetBit) == 0) {
139+
num1 ^= num;
140+
} else {
141+
num2 ^= num;
142+
}
143+
}
144+
145+
return new int[]{num1, num2};
146+
}
147+
}
148+
149+
// Alternative approach using recursive
150+
class SolutionRecursive {
151+
public int[] singleNumber(int[] nums) {
152+
int xor = 0;
153+
for (int num : nums) {
154+
xor ^= num;
155+
}
156+
157+
int rightmostSetBit = xor & (-xor);
158+
int[] result = new int[2];
159+
160+
singleNumberHelper(nums, 0, rightmostSetBit, result);
161+
162+
return result;
163+
}
164+
165+
private void singleNumberHelper(int[] nums, int index, int rightmostSetBit, int[] result) {
166+
if (index >= nums.length) {
167+
return;
168+
}
169+
170+
if ((nums[index] & rightmostSetBit) == 0) {
171+
result[0] ^= nums[index];
172+
} else {
173+
result[1] ^= nums[index];
174+
}
175+
176+
singleNumberHelper(nums, index + 1, rightmostSetBit, result);
177+
}
178+
}
179+
180+
// Alternative approach using mathematical
181+
class SolutionMathematical {
182+
public int[] singleNumber(int[] nums) {
183+
Set<Integer> set = new HashSet<>();
184+
long sum = 0;
185+
long uniqueSum = 0;
186+
187+
for (int num : nums) {
188+
sum += num;
189+
if (set.add(num)) {
190+
uniqueSum += num;
191+
}
192+
}
193+
194+
int diff = (int) ((2 * uniqueSum - sum) / 2);
195+
int[] result = new int[2];
196+
197+
for (int num : nums) {
198+
if (set.contains(num - diff)) {
199+
result[0] = num;
200+
result[1] = num - diff;
201+
break;
202+
}
203+
}
204+
205+
return result;
206+
}
207+
}
208+
209+
// More concise version
210+
class SolutionConcise {
211+
public int[] singleNumber(int[] nums) {
212+
int xor = 0;
213+
for (int num : nums) xor ^= num;
214+
215+
int rightmostSetBit = xor & (-xor);
216+
int num1 = 0, num2 = 0;
217+
218+
for (int num : nums) {
219+
if ((num & rightmostSetBit) == 0) {
220+
num1 ^= num;
221+
} else {
222+
num2 ^= num;
223+
}
224+
}
225+
226+
return new int[]{num1, num2};
227+
}
228+
}

0 commit comments

Comments
 (0)