目录
[415. 字符串相加](#415. 字符串相加)
[43. 字符串相乘](#43. 字符串相乘)
[2549. 统计桌面上的不同数字](#2549. 统计桌面上的不同数字)
[3507. 移除最小数对使数组有序 I](#3507. 移除最小数对使数组有序 I)
[3175. 找到连续赢 K 场比赛的第一位玩家](#3175. 找到连续赢 K 场比赛的第一位玩家)
[537. 复数乘法](#537. 复数乘法)
[2352. 相等行列对](#2352. 相等行列对)
[2177. 找到和为给定整数的三个连续整数](#2177. 找到和为给定整数的三个连续整数)
[3354. 使数组元素等于零](#3354. 使数组元素等于零)
[999. 可以被一步捕获的棋子数](#999. 可以被一步捕获的棋子数)
总结
字符串高精度
删除元素: nums.erase(nums.begin()+index+1);
双指针比较
find函数查找int index=s.find('+');
stoi可转化符号
pair函数pair<int,int> 返回return {a,b}; 接收auto [a,b]=
哈希表string存数字带间隔
前缀和模拟
方向数组搜索信息
函数改字母大小写c = tolower((unsigned char)c);
415. 字符串相加
字符串模拟高精度加法
cpp
class Solution {
public:
string addStrings(string num1, string num2) {
int i = num1.size() - 1;
int j = num2.size() - 1;
int carry = 0;
string ans = "";
while (i >= 0 && j >= 0) {
int res = (num1[i--] - '0') + (num2[j--] - '0') + carry;
carry = res / 10;
res %= 10;
ans = to_string(res) + ans;
}
while (i >= 0) {
int res = num1[i--] - '0' + carry;
carry = res / 10;
res %= 10;
ans = to_string(res) + ans;
}
while (j >= 0) {
int res = num2[j--] - '0' + carry;
carry = res / 10;
res %= 10;
ans = to_string(res) + ans;
}
if(carry){
ans=to_string(carry)+ans;
}
return ans;
}
};
43. 字符串相乘
法一:借助上一题的加法
cpp
class Solution {
string ans = "0";
void add(string& t) {
string res = "";
int i = ans.size() - 1;
int j = t.size() - 1;
int carry = 0;
while (i >= 0 && j >= 0) {
int n = (ans[i--] - '0') + (t[j--] - '0') + carry;
carry = n / 10;
n %= 10;
res = to_string(n) + res;
}
while (i >= 0) {
int n = (ans[i--] - '0') + carry;
carry = n / 10;
n %= 10;
res = to_string(n) + res;
}
while (j >= 0) {
int n = (t[j--] - '0') + carry;
carry = n / 10;
n %= 10;
res = to_string(n) + res;
}
if(carry)res=to_string(carry)+res;
ans=res;
}
public:
string multiply(string num1, string num2) {
if(num1=="0"||num2=="0")return "0";
for (int i = num2.size() - 1; i >= 0; i--) {
string t = "";
int carry = 0;
for (int j = num1.size()-1; j >= 0; j--) {
int n = (num2[i] - '0') * (num1[j] - '0') + carry;
carry = n / 10;
n %= 10;
t = to_string(n) + t;
}
if(carry)t=to_string(carry)+t;
int k = num2.size() - i-1;
while (k--)
t += '0';
add(t);
}
return ans;
}
};
法二:创建 vector<int> res(n1+n2, 0),把每对位乘好累加到对应位置,最后把 vector 转为字符串并去掉前导零
cpp
class Solution {
public:
string multiply(string num1, string num2) {
if (num1 == "0" || num2 == "0") return "0";
int n1 = num1.size(), n2 = num2.size();
vector<int> res(n1 + n2, 0);
// 从低位到高位乘并加到 res 的适当位置
for (int i = n1 - 1; i >= 0; --i) {
int a = num1[i] - '0';
for (int j = n2 - 1; j >= 0; --j) {
int b = num2[j] - '0';
int mul = a * b;
int p1 = i + j; // 高位索引
int p2 = i + j + 1; // 低位索引
int sum = mul + res[p2];
res[p2] = sum % 10;
res[p1] += sum / 10;
}
}
// 转为字符串并去掉前导0
string ans;
int i = 0;
while (i < (int)res.size() && res[i] == 0) ++i;
for (; i < (int)res.size(); ++i) ans.push_back('0' + res[i]);
return ans.empty() ? "0" : ans;
}
};
2549. 统计桌面上的不同数字
简单的思维题
cpp
class Solution {
public:
int distinctIntegers(int n) {
if(n==1)return 1;
return n-1;
}
};
3507. 移除最小数对使数组有序 I
删除元素: nums.erase(nums.begin()+index+1);
cpp
class Solution {
public:
int minimumPairRemoval(vector<int>& nums) {
int ans=0;
while(nums.size()>1){
bool flag=true;
int minsum=INT_MAX;
int index=-1;
for(int i=0;i<nums.size()-1;i++){
int sum=nums[i]+nums[i+1];
if(nums[i]>nums[i+1])flag=false;
if(sum<minsum){
minsum=sum;
index=i;
}
}
if(flag)break;
ans++;
nums[index]=minsum;
nums.erase(nums.begin()+index+1);
}
return ans;
}
};
3175. 找到连续赢 K 场比赛的第一位玩家
暴力超时
cpp
class Solution {
public:
int findWinningPlayer(vector<int>& skills, int k) {
vector<vector<int>> s(skills.size(), vector<int>(3));
for (int i = 0; i < skills.size(); i++) {
s[i][0] = skills[i];
s[i][1] = i;
s[i][2] = 0;
}
int p = -1;
while (p == -1) {
if (s[0][0] > s[1][0]) {
s[0][2]++;
s[1][1] = 0;
if (s[0][2] == k)p = s[0][1];
s.push_back({s[1][0], s[1][1], s[1][2]});
s.erase(s.begin() + 1);
} else {
s[1][2]++;
s[0][1] = 0;
if (s[1][2] == k)p = s[1][1];
s.push_back({s[0][0], s[0][1], s[0][2]});
s.erase(s.begin());
}
}
return p;
}
};
优化:双指针维护擂主和连胜
cpp
class Solution {
public:
int findWinningPlayer(vector<int>& skills, int k) {
int champ=0;
int win=0;
for(int i=1;i<skills.size();i++){
if(skills[champ]>skills[i]){
win++;
}
else {
win=1;
champ=i;
}
if(win==k)return champ;
}
return champ;
}
};
537. 复数乘法
有点繁琐,但是清晰易懂
cpp
class Solution {
public:
string complexNumberMultiply(string num1, string num2) {
int n11 = 0;
int n12 = 0;
int n21 = 0;
int n22 = 0;
string n = "";
int i = 0;
for (i = 0; i < num1.size(); i++) {
if (num1[i] == '+')
break;
n += num1[i];
}
n11 = stoi(n);
n = "";
for (int j = i + 1; j < num1.size(); j++) {
if (num1[j] >= '0' && num1[j] <= '9')
n += num1[j];
}
n12 = stoi(n);
if (num1[i + 1] == '-')
n12 = -n12;
n = "";
for (i = 0; i < num2.size(); i++) {
if (num2[i] == '+')
break;
n += num2[i];
}
n21 = stoi(n);
n = "";
for (int j = i + 1; j < num2.size(); j++) {
if (num2[j] >= '0' && num2[j] <= '9')
n += num2[j];
}
n22 = stoi(n);
if (num2[i + 1] == '-')
n22 = -n22;
int ans1 = n11 * n21 - n12 * n22;
int ans2 = n11 * n22 + n12 * n21;
string ans = "";
if (ans1 < 0) ans+='-';
ans += to_string(abs(ans1));
ans += '+';
if (ans2 < 0) ans+='-';
ans += to_string(abs(ans2));
ans+='i';
return ans;
}
};
实际上stoi本身就能解析带符号的字符串,不用判断负号
查找+可以用find函数返回下标
优化:
cpp
class Solution {
pair<int,int> parse(string& s){
int index=s.find('+');
int a=stoi(s.substr(0,index));
int b=stoi(s.substr(index+1,s.size()-index-2));
return {a,b};
}
public:
string complexNumberMultiply(string num1, string num2) {
auto [a,b]=parse(num1);
auto [c,d]=parse(num2);
int real=a*c-b*d;
int image=a*d+b*c;
return to_string(real)+'+'+to_string(image)+'i';
}
};
2352. 相等行列对
哈希表存储重复行/列,注意用string存储数字时,要在两数中间加个符号避免特殊情况,例如:
\[11,1\],\[1,11\]\],存储时若不加间隔符号,就都是"111"
```cpp
class Solution {
public:
int equalPairs(vector