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
}
发布了60 篇原创文章 · 获赞 0 · 访问量 1451

猜你喜欢

转载自blog.csdn.net/ClassmateLin/article/details/104324595
今日推荐