1. 程式人生 > 其它 >劍指 Offer 56 - II. 陣列中數字出現的次數 II(map、位運算)2

劍指 Offer 56 - II. 陣列中數字出現的次數 II(map、位運算)2

技術標籤:LeetCode

在一個數組 nums 中除一個數字只出現一次之外,其他數字都出現了三次。請找出那個只出現一次的數字。

示例 1:

輸入:nums = [3,4,3,3]
輸出:4
示例 2:

輸入:nums = [9,1,7,9,7,9,7]
輸出:1

解法一:雜湊map

class Solution {
// 使用 HashMap 記錄各個數字出現的次數
    public int singleNumber(int[] nums) {
        Map<Integer, Integer> map = new HashMap();

        for(int i = nums.length - 1; i >= 0; --i){
            int key = nums[i];
            if(!map.containsKey(key)){
                // 如果之前沒有遇到這一數字,則放入 map 中
                map.put(key, 1);
            }else{
                // 如果之前遇到過這一數字,則出現次數加 1
                map.put(key, map.get(key) + 1);
            }
        }

        for(Map.Entry<Integer, Integer> entry: map.entrySet()){
            if(entry.getValue() == 1){
                return entry.getKey();
            }
        }
        return -1;
    }
}

解法二:位運算

public class Solution {
	
    public int singleNumber(int[] nums) {//本演算法同樣適用於陣列nums中存在負數的情況
        if(nums.length==0) return -1;//輸入陣列長度不符合要求,返回-1;
        int[] bitSum = new int[32];//java int型別有32位,其中首位為符號位
        int res=0;
        for(int num:nums){
            int bitMask=1;//需要在這裡初始化,不能和res一起初始化
            for(int i=31;i>=0;i--){//bitSum[0]為符號位
            	//這裡同樣可以通過num的無符號右移>>>來實現,否則帶符號右移(>>)左側會補符號位,對於負數會出錯。
            	//但是不推薦這樣做,最好不要修改原陣列nums的資料
                if((num&bitMask)!=0) bitSum[i]++;//這裡判斷條件也可以寫為(num&bitMask)==bitMask,而不是==1
                bitMask=bitMask<<1;//左移沒有無符號、帶符號的區別,都是在右側補0
            }
        }
        for(int i=0;i<32;i++){//這種做法使得本演算法同樣適用於負數的情況
            res=res<<1;
            res+=bitSum[i]%3;//這兩步順序不能變,否則最後一步會多左移一次
        }
        return res;
    }
}