第一次解題思路:
- 遍歷數組,將數字和出現的次數裝到map集合
- 遍歷map集合,取到題目要求值 (其實不能用Map(空間復雜度O(n)))
public int[] singleNumbers(int[] nums) {
Map<Integer,Integer> map=new HashMap<>();
for(int num:nums){
if(map.containsKey(num)){
map.put(num,map.get(num)+1);
}else{
map.put(num, 1);
}
}
int [] ans=new int[2];
int count=0;
for(Map.Entry<Integer,Integer>entry:map.entrySet()){
if(entry.getValue()==1){
ans[count++]=entry.getKey();
}
}
return ans;
}
優化
解題思路:分組位運算
題目要求時間復雜度O(n),空間復雜度為O(1),因此不能用map(空間復雜度O(n))
代碼如下:
//使用分組位運算
public int[] singleNumbers3(int[] nums) {
//因為只有兩個數出現一次,數組全部元素進行異或運算的值 等同於 這個兩個元素異或運算的值
int k=0;
for(int num:nums){
k^=num;
}
//兩個數異或值不等於0 說明什么?說明這兩個數不同 那這兩個數在哪一位不同 對應位的異或值為1的地方不同
//兩個不同的數異或運算的結果 k 對k從低位往高位尋找 兩個數某位不同的所在位置 (即k從最低位開始 首次出現'1'的位置)
//找到區分值,就可以將這兩個數 分到 兩個不同分組
int first=1;
while((first&k)==0){
first<<=1;
}
//0跟數異或等於數本身 相同數異或等於0
//在各自分組中 只有一個數出現了一次 其他數都出現兩次
//各個分組 各自異或運算 結果值為 只出現過一次的數
int a=0;
int b=0;
for(int num:nums){
if((num&first)==0){
a^=num;
}else{
b^=num;
}
}
return new int[]{a,b};
}