1. 程式人生 > >23.位元位計數-Leetcode 338(python)

23.位元位計數-Leetcode 338(python)

  • 題目描述

給定一個非負整數 num。對於 0 ≤ i ≤ num 範圍中的每個數字 i ,計算其二進位制數中的 1 的數目並將它們作為陣列返回。

  • 示例

示例 1:

輸入: 2
輸出: [0,1,1]
示例 2:

輸入: 5
輸出: [0,1,1,2,1,2]
進階:

給出時間複雜度為O(n*sizeof(integer))的解答非常容易。但你可以線上性時間O(n)內用一趟掃描做到嗎?
要求演算法的空間複雜度為O(n)。
你能進一步完善解法嗎?要求在C++或任何其他語言中不使用任何內建函式(如 C++ 中的 __builtin_popcount)來執行此操作。


  • 解決思路

一開始看到通過率那麼高,興致盎然要自己做出來,然後從0到15的二進位制數寫完了,愣是看不出有啥規律,腦子裡沒有那種意識,咋都沒辦法。網上大神的解決方案:觀察發現,1的二進位制中數字1的個數是0的加1(),2和3的是0和1的分別加1,4567的是0123的分別加1。找到一種神奇的規律。

0     0 0
1     1 1
2    10 1
3    11 2
4   100 1
5   101 2
6   110 2
7   111 3
8  1000 1
9  1001 2
10 1010 2
11 1011 3
12 1100 2
13 1101 3
14 1110 3
15 1111 4
  • 程式碼
class Solution(object):
    def countBits(self, num):
        """
        :type num: int
        :rtype: List[int]
        """
        List1 = [0]
        
        while(len(List1)<=num):
            List2 = [i+1 for i in List1]
            List1 = List1 + List2
            
        return List1[:num+1]
  • 解決思路二

觀察發現:偶數的二進位制中1的個數和其一半的數的二進位制個數相等,奇數的二進位制中1的個數是其一半的數的二進位制中1的個數加1.比如2和4都是1,3和6都是2。5是2,2是1;7是3,3是2.

另外,整數對應的二進位制數邏輯右移一位,就等於除2操作。

  • 程式碼二
class Solution(object):
    def countBits(self, num):
        """
        :type num: int
        :rtype: List[int]
        """
        List1 = [0]
        
        for i in range(1,num+1):
            #>>1為邏輯右移1位,等於除2操作
            #偶數對2取餘為0,奇數對2取餘為1
            List1.append(List1[i>>1]+(i%2))
            
        return List1