137. 只出現一次的數字 II

中等 位運算 數組

思路

假如現在 k=1,m=3k = 1, m = 3 ,陣列是 [1,1,1,3,3,3,5,5,5,4][1,1,1,3,3,3,5,5,5,4]。 首先將每個數字都轉成二進制,並記錄每個位置出現的次數。

數字\位置012001m00011mm0101m0m10000k總和3mmm+k總和%m00k\begin{array}{c|c|c|c} \small\text{數字\textbackslash位置} & 0 & 1 & 2 \\\hline 001 & m & 0 & 0 \\\hline 011 & m & m & 0 \\\hline 101 & m & 0 & m \\\hline 100 & 0 & 0 & k \\\hline \small{總和} & 3m & m & m + \blue{k} \\\hline \small{總和}\%{m} & 0 & 0 & \blue{k} \end{array}
  • 11:對二進制的001001來說,它會在位置00一共給出mm次的貢獻。
  • 33:對二進制的011011來說,它會在位置0,10,1一共給出mm次的貢獻。
  • 55:對二進制的101101來說,它會在位置0,20,2一共給出mm次的貢獻。
  • 44:對二進制的100100來說,它會在位置22一共給出kk次的貢獻。 若是不考慮出現kk次的數字44,每個位置出現的次數都會是mm的倍數,因此,只要將各自位置的總和%m\%{m}之後,就能反推出出現kk次的數字了。

程式碼

位運算

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        const int m = 3;
        int cnt[32]{};
        for(int num : nums) {
            for(int i = 0; i < 32; ++i) {
                cnt[i] += (num >> i) & 1;
            }
        }
        int res = 0;
        for(int i = 0; i < 32; ++i) {
            if(cnt[i] % m != 0) {
                res |= 1 << i;
            }
        }
        return res;
    }
};

複雜度分析

  • 時間複雜度:O(n)O(n)
  • 空間複雜度:O(1)O(1)

顯示設定

背景線條
顯示背景網格線條
懸停發光
滑鼠懸停時顯示霓虹效果
聚光燈
跟隨滑鼠的聚光燈效果
背景透明度
開啟透明玻璃效果
主題顏色
自訂主要顏色