1. 程式人生 > 實用技巧 >劍指Offer_#56-II_ 陣列中數字出現的次數II

劍指Offer_#56-II_ 陣列中數字出現的次數II

劍指Offer_#56-II_ 陣列中數字出現的次數II

劍指offer

Contents

題目

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

輸入:nums = [3,4,3,3]
輸出:4

示例 2:

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

限制:

1 <= nums.length <= 10000
1 <= nums[i] < 2^31

思路分析

思路是統計數字的二進位制表示中每一位出現的次數。

  • 對於出現3次的數字,每個二進位制位也出現3次;多組出現3次的數字疊加,每個二進位制位出現次數是3的倍數。
  • 再考慮只出現一次的數字,即我們的目標數字。目標數字中,出現1的二進位制位會增加到之前的統計次數中,使得這個位置出現1的總次數不再是3的倍數。

演算法流程

  1. 遍歷陣列,對於每個元素,迴圈右移位,通過掩碼1獲取到二進位制表示中每一位1出現的次數,儲存到一個輔助陣列中,索引表示第幾位,元素表示出現的次數。
  2. 遍歷剛才的輔助陣列,看每個元素對3取餘的結果
    • 若為0說明這一位出現了3的整數倍次,必然沒有在目標數字中出現過,所以不計算
    • 若不為0,說明這位數字出現在目標數中,res加上digit,也就是當前二進位制位的數量級(2n

解答

class Solution {
    public
int singleNumber(int[] nums)
{ int res = 0; //二進位制中每一位數字的數量級 int digit = 1; //統計二進位制表示中每一位出現的總個數 int[] numTimes = new int[32]; for(int num:nums){ for(int i = 0; i <= 31;i++){ //如果第i位是1,那麼help[i]增加1 numTimes[i] += (num & 1
); //繼續統計下一位 num >>= 1; } } //遍歷help[]陣列 for(int times:numTimes){ res += digit * (times % 3); digit <<= 1; } return res; } }

複雜度分析

時間複雜度:O(n),兩層迴圈中,第二層迴圈次數是常數,所以還是O(n)。
空間複雜度:O(1),藉助一個輔助陣列,其長度是常數。