模拟题刷题2

目录

总结

[415. 字符串相加](#415. 字符串相加)

[43. 字符串相乘](#43. 字符串相乘)

[2549. 统计桌面上的不同数字](#2549. 统计桌面上的不同数字)

[3507. 移除最小数对使数组有序 I](#3507. 移除最小数对使数组有序 I)

[3175. 找到连续赢 K 场比赛的第一位玩家](#3175. 找到连续赢 K 场比赛的第一位玩家)

[537. 复数乘法](#537. 复数乘法)

[2352. 相等行列对](#2352. 相等行列对)

[2177. 找到和为给定整数的三个连续整数](#2177. 找到和为给定整数的三个连续整数)

[3354. 使数组元素等于零](#3354. 使数组元素等于零)

[999. 可以被一步捕获的棋子数](#999. 可以被一步捕获的棋子数)

CF282A

CF158A

CF263A

CF112A


总结

字符串高精度

删除元素: 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;
}
相关推荐
通信小呆呆10 分钟前
Hankel结构及其快速算法详解
线性代数·算法·机器学习
四代水门10 分钟前
服务端倒带(Server-Side Rewind)命中判定系统
java·前端·算法
吃好睡好便好11 分钟前
矩阵的左除和右除
人工智能·学习·线性代数·算法·矩阵
江屿风17 分钟前
C++图的基本概念流食般投喂-竞赛编
开发语言·数据结构·c++·笔记·算法·图论
Halo_tjn20 分钟前
JDBC 技术的使用
java·算法
Byte不洛23 分钟前
哈希表原理 + 冲突解决 + C++实现
数据结构·c++·算法·哈希算法·散列表
Dillon Dong3 小时前
【风电控制】TI TMS320F28379D 双CPU架构解析与任务分布设计
嵌入式硬件·算法·变流器·风电控制
小羊在睡觉9 小时前
力扣84. 柱状图中最大的矩形
后端·算法·leetcode·golang·go
3DVisionary9 小时前
蓝光三维扫描:医疗制造的精度焦虑怎么解
人工智能·算法·制造·蓝光三维扫描·医疗制造·三维检测·义齿检测
好评笔记9 小时前
机器学习面试八股——常用损失函数
人工智能·深度学习·算法·机器学习·校招