Leetcode刷题笔记(C++)——位运算
整理一下刷题过程中的思路,在这里进行一下总结与分享。
github地址:https://github.com/lvjian0706/Leetcode-solutions
github项目是刚刚新建的,陆续会将整理的代码以及思路上传上去,代码是基于C++与python的。同时会将基础的排序算法等也一并进行整理上传。
136. 只出现一次的数字
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
示例 1:
输入: [2,2,1]
输出: 1
示例 2:
输入: [4,1,2,1,2]
输出: 4
class Solution {
public:
/*
由于时间和空间限制,所以使用二进制的异或运算解答即可;
*/
int singleNumber(vector<int>& nums) {
int ans = nums[0];
for(int i=1; i<nums.size(); i++){
ans ^= nums[i];
}
return ans;
}
};
191. 位1的个数
编写一个函数,输入是一个无符号整数,返回其二进制表达式中数字位数为 ‘1’ 的个数(也被称为汉明重量)。
示例 1:
输入:00000000000000000000000000001011
输出:3
解释:输入的二进制串 00000000000000000000000000001011 中,共有三位为 ‘1’。
示例 2:
输入:00000000000000000000000010000000
输出:1
解释:输入的二进制串 00000000000000000000000010000000 中,共有一位为 ‘1’。
示例 3:
输入:11111111111111111111111111111101
输出:31
解释:输入的二进制串 11111111111111111111111111111101 中,共有 31 位为 ‘1’。
方法1:
class Solution {
public:
/*
返回二进制表达式中数字位数为 ‘1’ 的个数:
求二进制数(对2取余后整除2),当该位为1时,ans++;
*/
int hammingWeight(uint32_t n) {
int ans = 0;
while(n!=0){
ans += (n % 2);
n /= 2;
}
return ans;
}
};
方法2:
class Solution {
public:
/*
返回二进制表达式中数字位数为 ‘1’ 的个数:
n = n & (n-1) : 将最后一个1置0;
将最后一个1循环置0,直到所有位上都是0;
*/
int hammingWeight(uint32_t n) {
int ans = 0;
while(n){
n = n & (n-1);
ans++;
}
return ans;
}
};
260. 只出现一次的数字 III
给定一个整数数组 nums,其中恰好有两个元素只出现一次,其余所有元素均出现两次。 找出只出现一次的那两个元素。
示例 :
输入: [1,2,1,3,2,5]
输出: [3,5]
class Solution {
public:
/*
找出只出现一次的那两个元素:因为是常数空间,考虑位运算:
x & (-x) :保留位中最右边1,且将其余的1设为0。
1. xy ^= nums[i]:先找到只出现过一次的两个数的异或结果;
2. dif = xy & (-xy):找出x与y不同的一位(最右边一位);
3. x ^= nums[i]:找到x;
4. xy^x:找到y;
*/
vector<int> singleNumber(vector<int>& nums) {
vector<int> ans;
int xy=0;
for(int i=0; i<nums.size(); i++){
xy ^= nums[i];
}
int dif = xy & (-xy);
int x = 0;
for(int i=0; i<nums.size(); i++){
if(nums[i]&dif){
x ^= nums[i];
}
}
ans.push_back(x);
ans.push_back(xy^x);
return ans;
}
};
338. 比特位计数
给定一个非负整数 num。对于 0 ≤ i ≤ num 范围中的每个数字 i ,计算其二进制数中的 1 的数目并将它们作为数组返回。
示例 1:
输入: 2
输出: [0,1,1]
示例 2:
输入: 5
输出: [0,1,1,2,1,2]
class Solution {
public:
/*
对于0≤i≤num范围中的每个数字i,计算其二进制数中的1的数目并将它们作为数组返回:动态规划问题
1. 奇数:二进制表示中,奇数一定比前面那个偶数多一个 1,因为多的就是最低位的 1。
2. 偶数:二进制表示中,偶数中 1 的个数一定和除以 2 之后的那个数一样多。因为最低位是 0,除以 2 就是右移一位,也就是把那个 0 抹掉而已,所以 1 的个数是不变的。
*/
vector<int> countBits(int num) {
vector<int> dp(num+1);
dp[0] = 0;
for(int i=1; i<num+1; i++){
if(i%2==0){
dp[i] = dp[i/2];
}
else{
dp[i] = dp[i-1] + 1;
}
}
return dp;
}
};