LeetCode系列之位运算专题
1. 位运算题目概述
https://leetcode-cn.com/tag/bit-manipulation/
2. 典型题目
2.1 汉明距离
https://leetcode-cn.com/problems/hamming-distance/
int hammingDistance(int x, int y) { return hammingWeight(x ^ y); }
运用下述题目的hanmmingWeight方法,很容易计算。
时间复杂度O(1),空间复杂度O(1)。
2.2 二进制链表转整数
https://leetcode-cn.com/problems/convert-binary-number-in-a-linked-list-to-integer/
2.3 多数元素
https://leetcode-cn.com/problems/majority-element/
2.4 位1的个数
https://leetcode-cn.com/problems/number-of-1-bits/
int hammingWeight(uint32_t n) { int count = 0; while (n) { n = n & (n - 1); count++; } return count; }
这种算法有一个名字:布莱恩·克尼根算法。
时间复杂度O(1),空间复杂度O(1)。
2.5 比特位计数
https://leetcode-cn.com/problems/counting-bits/
用到了成员变量,所以就把整个类定义都copy过来了
class Solution { public: vector<int> countBits(int num) { if (num > index_) { fillBitsNumberVector(num); } return extractBitsNumberVector(num); } private: int countNumberOf1(int n) { int count = 0; while (n) { n = n & (n - 1); count++; } return count; } void fillBitsNumberVector(int num) { for (int i = index_ + 1; i <= num; i++) { bitsNumberVec_.push_back(countNumberOf1(i)); } } vector<int> extractBitsNumberVector(int num) { vector<int> ivec = bitsNumberVec_; ivec.resize(num + 1); return ivec; } vector<int> bitsNumberVec_; int index_ = -1; };
经过试验发现,resize要比手动copy要快一些。
时间复杂度O(N),空间复杂度O(N)。
2.6 只出现一次的数字
https://leetcode-cn.com/problems/single-number/
条件最强的一个
int singleNumber(vector<int>& nums) { int ret = 0; for (int i : nums) { ret ^= i; } return ret; }
时间复杂度O(N),空间复杂度O(1)。
https://leetcode-cn.com/problems/single-number-ii/
https://leetcode-cn.com/problems/single-number-iii/
2.7 2的幂
https://leetcode-cn.com/problems/power-of-two/
两个注意点
- int64转一下,不然在输入INT_MIN时,会溢出
- n == 0时,要额外处理
bool isPowerOfTwo(int n) { if (n == 0) return false; int64_t m = n; m = m & (m - 1); return m == 0; }
时间复杂度O(1),空间复杂度O(1)。
2.8 数字的补数
https://leetcode-cn.com/problems/number-complement/
2.9 找不同
https://leetcode-cn.com/problems/find-the-difference/
思路和 2.7 一模一样,只是把异或运用到了char类型上,char类型本质上也是范围小一点的整型。所以,没毛病。
char findTheDifference(string s, string t) { char ret = 0; for (char c : s) { ret ^= c; } for (char c : t) { ret ^= c; } return ret; }
时间复杂度O(N),空间复杂度O(1)。
2.10 两整数之和
https://leetcode-cn.com/problems/sum-of-two-integers/
int getSum(int a, int b) { while(b) { unsigned int carry = a & b; a = a ^ b; b = carry << 1; } return a; }
carry一定要设置成unsigned int类型,否则会遇到“runtime error: left shift of 1073741824 by 1 places cannot be represented in type 'int'”的问题。
时间复杂度O(1),跟int的size有关;空间复杂度O(1)。