法一:很普通很普通的做法
//法一:很普通的做法
public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
if(array == null || array.length == 0)
return;
HashMap<Integer, Integer> maps = new HashMap<>();
for(int i = 0; i < array.length; i++){
if(maps.containsKey(array[i])){
int tmp = maps.get(array[i])+1;
maps.put(array[i] , tmp);
}else
maps.put(array[i], 1);
}
List<Integer> res = new ArrayList<>();
for(Map.Entry<Integer, Integer> entry: maps.entrySet()){
if(entry.getValue() == 1)
res.add(entry.getKey());
if(res.size() >= 2)
break;
}
num1[0] = res.get(0);
num2[0] = res.get(1);
}
}
法二: 通過異或的方式來找出兩個出現一次的數 orz
思路是這樣子的:
- 因爲這個數組中除了這兩個數以外其他的數都是成雙成對地存在的,所以當那些成雙成對的數都異或完了就只爲0了,因此捏,如果數組裏只有一個出現一次的數的話,這時候全部異或完的結果就是這個只出現一次的數啦;
- 那現在有兩個要怎麼辦?異或完的結果記爲res吧, res此時爲這兩個數某一位或者幾位不同而產生的結果。(比如4^6 = 2,即0100 ^ 0110 = 0010)
- 此時我們要做的是根據res中從右往左數第一位不爲0的idx來將兩個分到兩隊(4跟6中,idx =1)
- 分完了就各放各的地方即可
public class Solution { public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) { if(array == null || array.length == 0) return; if(array.length == 2){ num1[0] = array[0]; num2[0] = array[1]; return; } int xorResult = 0; for(int i = 0; i < array.length; i++) xorResult ^= array[i]; //查看爲1的是在哪一位上 int index = findDiff(xorResult); //index位就是這兩個只出現一次的數第一次不一樣的地方,以此來將他們分到兩個數組 for(int i = 0; i < array.length;i++){ if(isOneInThisBit(array[i], index)) num1[0] ^= array[i]; else num2[0] ^= array[i]; } } //找到那個異或爲1的位數是哪位,因爲這個說明這兩個只出現一次的數在此位上不一樣 private int findDiff(int number){ int idx = 0; while((number & 1) != 1 && idx < 32){ number >>>= 1; idx++; } return idx; } //判斷該數在idx位上是否爲1,以此將兩個不一樣的數分開 private boolean isOneInThisBit(int number, int idx){ return ((number >>>=idx)&1)== 1; } }