劍指 數組中只出現1次的兩個數

法一:很普通很普通的做法

//法一:很普通的做法
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;
        }
    }

     

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章