目录
[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<vector<int>>& grid) {
unordered_map<string,int>mapR;
unordered_map<string,int>mapC;
for(int i=0;i<grid.size();i++){
string a="";
string b="";
for(int j=0;j<grid.size();j++){
a+=to_string(grid[i][j]);
a+='+';
b+=to_string(grid[j][i]);
b+='+';
}
mapR[a]++;
mapC[b]++;
}
int ans=0;
for(auto& [key,val]:mapR)ans+=val*mapC[key];
return ans;
}
};
2177. 找到和为给定整数的三个连续整数
感觉不是中等题
cpp
class Solution {
public:
vector<long long> sumOfThree(long long num) {
if((num/3)*3==num)return {num/3-1,num/3,num/3+1};
else return {};
}
};
3354. 使数组元素等于零
前缀和模拟
打砖块。若初始方向向右,则应保证左右两边砖块相等或右边比左边多1。若初始方向向左,则应保证左右两边砖块相等或左边比右边多1。
所以,ans在左右相等时+2,在左右差1时+1
可以先用sum统计总砖块
cpp
class Solution {
public:
int countValidSelections(vector<int>& nums) {
int ans=0;
int sum=0;
int pre=0;
for(int t:nums)sum+=t;
for(int t:nums){
if(t)pre+=t;
else {
if(pre*2==sum)ans+=2;
else if(abs(sum-pre*2)==1)ans++;
}
}
return ans;
}
};
999. 可以被一步捕获的棋子数
纯模拟
cpp
class Solution {
public:
int numRookCaptures(vector<vector<char>>& board) {
int ans=0;
int x,y;
int q=1;
for(int i=0;i<board.size();i++){
for(int j=0;j<board.size();j++){
if(board[i][j]=='R'){
x=i;
y=j;
q=0;
break;
}
}
if(!q)break;
}
int t=y;
while(t>=0){
if(board[x][t]=='p'){
ans++;
break;
}
else if(board[x][t]=='B'){
break;
}
else t--;
}
t=y;
while(t<board.size()){
if(board[x][t]=='p'){
ans++;
break;
}
else if(board[x][t]=='B'){
break;
}
else t++;
}
t=x;
while(t>=0){
if(board[t][y]=='p'){
ans++;
break;
}
else if(board[t][y]=='B'){
break;
}
else t--;
}
t=x;
while(t<board.size()){
if(board[t][y]=='p'){
ans++;
break;
}
else if(board[t][y]=='B'){
break;
}
else t++;
}
return ans;
}
};
优化:方向数组、for跳出逻辑
cpp
class Solution {
public:
int numRookCaptures(vector<vector<char>>& board) {
int x=-1;
int y=-1;
int n=board.size();
for(int i=0;i<n&&x==-1;i++){
for(int j=0;j<n;j++){
if(board[i][j]=='R'){
x=i;y=j;
}
}
}
int ans=0;
int dx[4]={0,-1,0,1};
int dy[4]={-1,0,1,0};
for(int i=0;i<4;i++){
int nx=x+dx[i];
int ny=y+dy[i];
while(nx>=0&&ny>=0&&nx<n&&ny<n){
char t=board[nx][ny];
if(t=='p'){
ans++;
break;
}
else if(t=='B')break;
else {
nx+=dx[i];
ny+=dy[i];
}
}
}
return ans;
}
};
CF282A
简单
cpp
void solve()
{
int n;
string t;
int x = 0;
cin >> n;
while (n--)
{
cin >> t;
if (t[1] == '+')
x++;
else
x--;
}
cout << x;
}
CF158A
想复杂了,只要两次for一次读入一次判断即可
cpp
void solve()
{
int n, k;
cin >> n >> k;
vector<int> s(n);
for (int i = 0; i < n; i++)
{
cin >> s[i];
}
int ans = 0;
int p = s[k - 1];
for (int i = 0; i < n; i++)
{
if (s[i] >= p && s[i])
{
ans++;
}
}
cout << ans;
}
CF263A
cpp
void solve()
{
int x, y;
vector<vector<int>> gra(5, vector<int>(5));
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 5; j++)
{
cin >> gra[i][j];
if (gra[i][j])
{
x = i;
y = j;
}
}
}
cout << abs(2 - x) + abs(2 - y);
}
CF112A
cpp
void solve()
{
string a, b;
cin >> a >> b;
for (int i = 0; i < a.size(); i++)
{
if (a[i] >= 'A' && a[i] <= 'Z')
{
a[i] = a[i] - 'A' + 'a';
}
if (b[i] >= 'A' && b[i] <= 'Z')
{
b[i] = b[i] - 'A' + 'a';
}
if (a[i] > b[i])
{
cout << 1;
return;
}
else if (a[i] < b[i])
{
cout << -1;
return;
}
}
cout << 0;
}
这是手动改大小和比较,优化版是调用函数
cpp
void solve() {
string a, b;
cin >> a >> b;
for (int i = 0; i < (int)a.size(); ++i) {
char ca = tolower((unsigned char)a[i]);
char cb = tolower((unsigned char)b[i]);
if (ca > cb) { cout << 1; return; }
if (ca < cb) { cout << -1; return; }
}
cout << 0;
}
或者
cpp
void solve() {
string a, b;
cin >> a >> b;
for (char& c : a) c = tolower((unsigned char)c);
for (char& c : b) c = tolower((unsigned char)c);
if (a > b) cout << 1;
else if (a < b) cout << -1;
else cout << 0;
}
