Leetcode ブラッシングノート (C++) - ビット操作
質問をブラッシュアップする過程でアイデアを整理し、ここにまとめて共有します。
github アドレス: https://github.com/lvjian0706/Leetcode-solutions
github プロジェクトは新しく作成されたばかりで、C++ と Python をベースに整理されたコードやアイデアが次々とアップロードされます。同時に、基本的な並べ替えアルゴリズムも並べ替えてアップロードされます。
136. 一度だけ現れる数字
空ではない整数の配列を指定すると、1 回しか出現しない特定の要素を除いて、各要素は 2 回出現します。1 回だけ出現する要素を見つけます。
説明:
アルゴリズムには線形時間計算量が必要です。余分なスペースを使わずに実行できますか?
例 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 では、合計 3 ビットが「1」です。
例 2:
入力: 00000000000000000000000010000000
出力: 1
説明: 入力バイナリ文字列 00000000000000000000000010000000 では、合計 1 ビットが「1」になります。
例 3:
入力: 11111111111111111111111111101
出力: 31
説明: 入力バイナリ文字列 11111111111111111111111111101 では、合計 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. 一度だけ現れる数字Ⅲ
整数配列 nums を指定すると、ちょうど 2 つの要素は 1 回だけ現れ、他のすべての要素は 2 回現れます。1 回だけ出現する 2 つの要素を見つけます。
例:
入力: [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. ビットを数える
負ではない整数が与えられます。0 ≤ i ≤ num の範囲内の各数値 i について、その 2 進数の 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;
}
};