Leetcode精選題解(Go)之bitmap算法

461.漢明距離

題目


兩個整數之間的漢明距離指的是這兩個數字對應二進制位不同的位置的數目。

給出兩個整數 x 和 y,計算它們之間的漢明距離。

注意:
0 ≤ x, y < 231.

示例:

輸入: x = 1, y = 4

輸出: 2

解釋:
1   (0 0 0 1)
4   (0 1 0 0)
       ↑   ↑

上面的箭頭指出了對應二進制位不同的位置。

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/hamming-distance
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。

題解

計算多少位不同,只需要將兩個樹進行異或操作,相同位置爲0,不相同爲1,那麼只需要統計1的個數即可。

代碼

// 計算二進制不同位置的數目
func hammingDistance(x int, y int) int {
    z := x ^ y  // 異或運算,相同爲0,不同爲1
    cnt := 0
    for z != 0 {
        if z & 1 == 1 {  // 與運算,兩個位都爲1時結果才爲1
            cnt++
        }
        z >>= 1  // 右移一位,高位補0
    }
    return cnt
}

136.只出現一次的數字

題目

給定一個非空整數數組,除了某個元素只出現一次以外,其餘每個元素均出現兩次。找出那個只出現了一次的元素。

說明:

你的算法應該具有線性時間複雜度。 你可以不使用額外空間來實現嗎?

示例 1:

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

輸入: [4,1,2,1,2]
輸出: 4

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/single-number
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。

題解

相同元素異或的結果爲0, 一個數字和0異或的結果等於其本身,
那麼將數組中所有的元素進行異或操作,那麼最後得到的數字就是不重複的那個數字。

代碼

// 找出數組中僅出現一次的數字
func singleNumber(nums []int) int {
    res := 0
    for _, v := range nums {
        res ^= v
    }
    return res
}

268.缺失的數字

題目

給定一個包含 0, 1, 2, ..., n 中 n 個數的序列,找出 0 .. n 中沒有出現在序列中的那個數。

示例 1:

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

輸入: [9,6,4,2,3,5,7,0,1]
輸出: 8
說明:
你的算法應具有線性時間複雜度。你能否僅使用額外常數空間來實現?

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/missing-number
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。

題解

  • 使用異或操作,將數組的元素和0~n的元素進行異或操作,最後得到的數字就是缺失的數字。
  • 數組的數字個數必定並0~n中的數字少一個,可以假定n不在數組中。

代碼

// 查找缺失的數字
func missingNumber(nums []int) int {
    res := 0
    
    for i := 0; i < len(nums); i++ {
        res = res ^ i ^ nums[i]
    }
    return res ^ len(nums)
}

260.只出現一次的數字III

題目

給定一個整數數組 nums,其中恰好有兩個元素只出現一次,其餘所有元素均出現兩次。 找出只出現一次的那兩個元素。

示例 :

輸入: [1,2,1,3,2,5]
輸出: [3,5]
注意:

結果輸出的順序並不重要,對於上面的例子, [5, 3] 也是正確答案。
你的算法應該具有線性時間複雜度。你能否僅使用常數空間複雜度來實現?

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/single-number-iii
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。

題解

兩個不相等的元素在位級表示上必定會有一位存在不同。

將數組的所有元素異或得到的結果爲不存在重複的兩個元素異或的結果。

diff &= -diff 得到出 diff 最右側不爲 0 的位,也就是不存在重複的兩個元素在位級表示上最右側不同的那一位,利用這一位就可以將兩個元素區分開來。

代碼

// 求數組中只出現一次的兩個數字
func singleNumber(nums []int) []int {
    diff := 0
    for _, v := range nums {
        diff ^= v
    }
    diff &= -diff  // 得到最右側不爲0的位
    res := make([]int, 2)
    for _, v := range nums {
        if v & diff == 0 {
            res[0] ^= v
        }else {
            res[1] ^= v
        }
    }
    return res
}

190.顛倒二進制位

題目

顛倒給定的 32 位無符號整數的二進制位。

 

示例 1:

輸入: 00000010100101000001111010011100
輸出: 00111001011110000010100101000000
解釋: 輸入的二進制串 00000010100101000001111010011100 表示無符號整數 43261596,
      因此返回 964176192,其二進制表示形式爲 00111001011110000010100101000000。
示例 2:

輸入:11111111111111111111111111111101
輸出:10111111111111111111111111111111
解釋:輸入的二進制串 11111111111111111111111111111101 表示無符號整數 4294967293,
      因此返回 3221225471 其二進制表示形式爲 10101111110010110010011101101001。
 

提示:

請注意,在某些語言(如 Java)中,沒有無符號整數類型。在這種情況下,輸入和輸出都將被指定爲有符號整數類型,並且不應影響您的實現,因爲無論整數是有符號的還是無符號的,其內部的二進制表示形式都是相同的。
在 Java 中,編譯器使用二進制補碼記法來表示有符號整數。因此,在上面的 示例 2 中,輸入表示有符號整數 -3,輸出表示有符號整數 -1073741825。

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/reverse-bits
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。

題解

使用位移運算進行左右顛倒。

代碼

func reverseBits(num uint32) uint32 {
    var res uint32 = 0
    for i:=0; i <32; i++ {
        res = (res << uint32(1)) + (num & uint32(1))
        //res = (res << uint32(1)) | (num & uint32(1))
    }
    return res
}

231. 2的冪

題目

給定一個整數,編寫一個函數來判斷它是否是 2 的冪次方。

示例 1:

輸入: 1
輸出: true
解釋: 20 = 1
示例 2:

輸入: 16
輸出: true
解釋: 24 = 16
示例 3:

輸入: 218
輸出: false

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/power-of-two
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。

題解

2的冪二進制表示中只有一個位置1,統計位1的個數是否等於1即可。

代碼

func isPowerOfTwo(n int) bool {
    cnt := 0
    for n != 0 {
        if cnt > 1 { // 提前退出循環
            return false
        }
        if n & 1 == 1{
            cnt++
        }
        n >>= 1
    }
    if cnt != 1 {
        return false
    }
    return true
}

338.比特位計數

題目

給定一個非負整數 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)來執行此操作。

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/counting-bits
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。

題解

第i個數的二進制中數含1的個數等於等於第(i&i-1)個數中二進制數中1的個數加1。

代碼

func countBits(num int) []int {
  dp := make([]int, num+1)
  for i:=1; i<= num; i++{
    dp[i] = dp[i & (i-1)] + 1
  }
  return dp
}
發佈了63 篇原創文章 · 獲贊 4 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章