[TOC]
本文主要记录前缀和的相关LeetCode题目的实现代码,直接给出本文各个题目的答案,供有需求的读者学习或复制。
一、二进制计数问题
461. 汉明距离(简单难度)
class Solution {
public:
int hammingDistance(int x, int y) {
// 方法一:进制转换
// int count=0;
// if(x==y)
// return 0;
// // 同时取位
// while(x!=0||y!=0){
// if(x%2!=y%2)
// count++;
// x=x/2;
// y=y/2;
// }
// return count;
// 方法二:位运算
int count=0;
int a=x^y;// 异或运算,相同为0,不同为1
while(a){
count+=a&1;// 查看最后一位是否是1
a>>=1;// 右移1位
}
return count;
}
};
191. 位1的个数(简单难度)
剑指 Offer 15. 二进制中1的个数(简单难度)
class Solution {
public:
int hammingWeight(uint32_t n) {
// 方法一:进制转换
// string kbits="";
// if(n==0) kbits="0";
// while(n){
// kbits=to_string(n%2)+kbits;
// n/=2;
// }
// //
// int res=0;
// for(char c:kbits){
// if(c=='1') res++;
// }
// return res;
// 方法二:位运算
int count = 0;
while (n) {
count += n & 1;
n>>=1;
}
return count;
}
};
190. 颠倒二进制位(简单难度)
class Solution {
public:
uint32_t reverseBits(uint32_t n) {
uint32_t rev = 0;
int power=31;
while(n){
rev+=(n&1)<<power;//左移32位
n>>=1;
power--;
}
return rev;
}
};
二、数组中元素出现的次数
1、一个数出现1次,其余数都出现2次
136. 只出现一次的数字(简单难度)
class Solution {
public:
int singleNumber(vector<int>& nums) {
// 方法一:位运算
// 数组中一定有奇数个元素,数组中的全部元素进行异或运算,结果即为只出现一次的数字
// int res=0;
// for(int num:nums) res^=num;
// return res;
// 方法二:位运算
int res=0;
for(int i=0;i<32;i++){
int mask=1<<i;//从右向左取第i位
int cnt = 0;//第i位出现的次数
// 遍历整个数组后的第i位出现了几次1
for (int num:nums) {
if ((num & mask) != 0) {
cnt++;
}
}
// 如果第i位没有出现3次则保留
if (cnt % 2 != 0) {
res |= mask;
}
}
return res;
// // 方法二:哈希法
// unordered_map<int,int> map;// 数字和出现次数
// // 遍历数组一遍统计频率
// for(int num:nums){
// map[num]++;
// }
// // 遍历哈希表
// for(auto it=map.begin();it!=map.end();++it){
// if(it->second==1)
// return it->first;
// }
// return -1;
}
};
2、一个数出现1次,其余数都出现3次
137. 只出现一次的数字 II(中等难度)
剑指 Offer 56 - II. 数组中数字出现的次数 II(中等难度)
剑指 Offer II 004. 只出现一次的数字(中等难度)
class Solution {
public:
int singleNumber(vector<int>& nums) {
// 方法一:位运算(异或)
// int ones=0;twos=0;
// for(int num:nums){
// ones=ones^num&(~twos);//x & ~x = 0;// num,0,0
// twos=twos^num&(~ones);//x & ~0 = x;// 0,num,0
// }
// return ones;
// 方法二:位运算
int res=0;
for(int i=0;i<32;i++){
int mask=1<<i;//从右向左取第i位
int cnt = 0;//第i位出现的次数
// 遍历整个数组后的第i位出现了几次1
for (int num:nums) {
if ((num & mask) != 0) {
cnt++;
}
}
// 如果第i位没有出现3次则保留
if (cnt % 3 != 0) {
res |= mask;
}
}
return res;
// 方法二:哈希法
// unordered_map<int,int> map;// 数字和出现次数
// // 遍历数组一遍统计频率
// for(int num:nums){
// map[num]++;
// }
// // 再次遍历遍历字符串
// for(int num:nums){
// if(map[num]==1)
// return num;
// }
// return -1;
}
};
3、两个数出现1次,其余数都出现2次
260. 只出现一次的数字 III(中等难度)
剑指 Offer 56 - I. 数组中数字出现的次数(中等难度)
class Solution {
public:
vector<int> singleNumber(vector<int>& nums) {
vector<int> res(2,0);
int aob=0;
for(int num:nums){
aob^=num;
}
// 取出最后一位
int lastBit = (aob == INT_MIN ? aob : aob & (-aob));// 防止溢出
for (int num : nums) {
// 分成2个数
if ((lastBit & num) != 0)
res[0] ^= num;
else
res[1] ^= num;
}
return res;
}
};
二、四则运算
1、两数加法
371. 两整数之和(简单难度)
剑指 Offer 65. 不用加减乘除做加法(简单难度)
面试题 17.01. 不用加号的加法(简单难度)
class Solution {
public:
int getSum(int a, int b) {
// 当进位部分不为0,说明需要继续加
while (a != 0) {
int temp = a ^ b;//非进位部分(没有添加进位部分),按位异或,
//异或这里可看做是相加但是不显现进位,比如5 ^ 3
/*0 1 0 1
0 0 1 1
------------
0 1 1 0 */
a = ((unsigned int)a & b) << 1; //进位部分,都是1是发生进位,对有符号左移的溢出保护处理
//相与为了让进位显现出来,比如5 & 3
/* 0 1 0 1
0 0 1 1
------------
0 0 0 1
上面的最低位1和1相与得1*/
b = temp;
}
return b;
}
};
67. 二进制求和(简单难度)
剑指 Offer II 002. 二进制加法(简单难度)
class Solution {
public:
string addBinary(string a, string b) {
string res;
// 从右向左同时遍历2个可能不等长的字符串
int i=a.length()-1;
int j=b.length()-1;
bool carry=false;
int sum=0;
while(i>=0||j>=0){
sum=0;
if(i>=0) sum+=a[i--]-'0';
if(j>=0) sum+=b[j--]-'0';
if(carry) sum+=1;
res =to_string(sum%2)+res;
carry=sum>=2?true:false;
}
// 如果有多余的进位
if(carry) res =to_string(1)+res;
return res;
}
};
989. 数组形式的整数加法(简单难度)
class Solution {
public:
vector<int> addToArrayForm(vector<int>& num, int k) {
vector<int> res;
// 从右向左同时遍历2个可能不等长的序列
int i=num.size()-1;
int sum=0;
bool carry=false;
while(i>=0||k){
sum=0;
if(i>=0)sum+=num[i--];
if(k){
sum+=k%10;
k/=10;
}
if(carry) sum+=1;
res.push_back(sum%10);
carry=sum>=10?true:false;
}
if(carry) res.push_back(1);
reverse(res.begin(),res.end());//反转
return res;
}
};
415. 字符串相加(简单难度)
class Solution {
public:
string addStrings(string num1, string num2) {
string res;
// 从右向左同时遍历2个可能不等长的字符串
int i=num1.length()-1;
int j=num2.length()-1;
bool carry=false;
int sum=0;
while(i>=0||j>=0){
sum=0;
if(i>=0) sum+=num1[i--]-'0';
if(j>=0) sum+=num2[j--]-'0';
if(carry) sum+=1;
res =to_string(sum%10)+res;
carry=sum>=10?true:false;
}
// 如果有多余的进位
if(carry) res =to_string(1)+res;
return res;
}
};