机考刷题之 17&18&19&20&21&22 LeetCode 1248&121&43&93&62&63

2026/3/14:

由于最近做了没来得及写详细题解,这里先把代码附上来,之后复习的时候再写。

LeetCode 1248:

题目

分析

前缀和+哈希

代码

cpp 复制代码
class Solution {
public:
    int numberOfSubarrays(vector<int>& nums, int k) {
        int n = nums.size();
        unordered_map<int,int>dp;
        dp[0] = 1;
        int sum = 0;
        int ans = 0;
        for(int i = 0 ;i<n;i++){
            if(nums[i]%2!=0){
                sum++;
            }
            int need = sum - k;
            if(dp.find(need)!=dp.end()){
                ans += dp[need];
            }
            dp[sum]++;
        }
        return ans;
    }
};

结果

LeetCode 121:

题目

分析

看的代码随想录的视频,动态规划,主要是dp数组的定义不容易想到。

代码

cpp 复制代码
class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int n = prices.size();
        vector<vector<int>>dp(n,vector<int>(2,0));
        dp[0][0] = -prices[0];
        dp[0][1] = 0;
        for(int i = 1;i < n;i++){
            dp[i][0] = max(-prices[i],dp[i-1][0]);
            dp[i][1] = max(prices[i]+dp[i-1][0],dp[i-1][1]);
        }
        return dp[n-1][1];
    }
};

结果

LeetCode 43:

题目

分析

其实就是大数乘法,想要转换为整型再乘得到答案,然后再转回字符串的话,大数会整型溢出。所以采用"竖式乘法"的方法。

代码

cpp 复制代码
class Solution {
public:
    string multiply(string num1, string num2) {
        if (num1 == "0" || num2 == "0") return "0";

        int m = num1.size(), n = num2.size();
        vector<int> res(m + n, 0);

        // 从右往左模拟乘法
        for (int i = m - 1; i >= 0; i--) {
            for (int j = n - 1; j >= 0; j--) {
                int mul = (num1[i] - '0') * (num2[j] - '0');
                int p1 = i + j, p2 = i + j + 1; // p2 是低位,p1 是高位
                int sum = mul + res[p2];

                res[p2] = sum % 10;
                res[p1] += sum / 10;
            }
        }

        // 转为字符串,跳过前导零
        string ans = "";
        int i = 0;
        while (i < res.size() && res[i] == 0) i++;
        for (; i < res.size(); i++) {
            ans += (res[i] + '0');
        }

        return ans.empty() ? "0" : ans;
    }
};

结果

LeetCode 93:

题目

分析

想到高中数学统计学的插板法求组和数,大概思路就是用插板法得到所有可能的组合,然后再判断每个组合是否合法。

代码

cpp 复制代码
class Solution {
public:
    vector<string> restoreIpAddresses(string s) {
        int n = s.length();
        vector<string>res;
        if(n < 4 || n>12) return res;
        // 辅助 lambda:判断一段是否合法
        auto isValid = [](const string& seg) -> bool {
            if (seg.empty() || seg.size() > 3) return false;
            if (seg[0] == '0' && seg.size() > 1) return false; // 前导零
            // 检查是否全为数字(题目保证输入是数字,可省略,但保留更健壮)
            for (char c : seg) {
                if (!isdigit(c)) return false;
            }
            int num = stoi(seg);
            return num >= 0 && num <= 255;
        };

        // 枚举三个分割点 i, j, k
        // s[0:i), s[i:j), s[j:k), s[k:n)
        for (int i = 1; i <= 3 && i < n - 2; ++i) {               // 第一段最多取3位,且后面至少留3个字符
            for (int j = i + 1; j <= i + 3 && j < n - 1; ++j) {   // 第二段最多3位,后面至少留2个
                for (int k = j + 1; k <= j + 3 && k < n; ++k) {   // 第三段最多3位,后面至少留1个
                    string a = s.substr(0, i);
                    string b = s.substr(i, j - i);
                    string c = s.substr(j, k - j);
                    string d = s.substr(k, n - k);

                    if (isValid(a) && isValid(b) && isValid(c) && isValid(d)) {
                        res.push_back(a + "." + b + "." + c + "." + d);
                    }
                }
            }
        }

        return res;
    }
};

结果

LeetCode 62:

题目

分析

同样是经典的动态规划问题,感觉就是二维的爬楼梯,方向固定为两个,dp[i][j]的方法来源于它的上方和左方,也就是

dp[i][j] = dp[i-1][j]+dp[i][j-1]

当然,要注意边界条件。

代码

cpp 复制代码
class Solution {
public:
    int uniquePaths(int m, int n) {
        vector<vector<int>>dp(m,vector<int>(n,0));//到(i,j)有几种方法
        for(int i = 0;i < m;i++){
            for(int j = 0;j < n;j++){//第一列和第一行都为1,因为只能有左边或者上边来
                if( i == 0 || j == 0)dp[i][j] = 1;
                else
                dp[i][j] = dp[i-1][j]+dp[i][j-1];
            }
        }
        return dp[m-1][n-1];
    }
};

结果

LeetCode 63:

题目

分析

和1比就是加入了障碍物,有了障碍物后,在初始化的时候,障碍物这里应该为0不变并且如果是第一列或者第一行位于障碍物及其后续位置(比如第一列在障碍物下面的或者第一行在障碍物右边的)也应该始终为0。后续遍历当到达障碍物时,直接跳过。

代码

cpp 复制代码
class Solution {
public:
    int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
        int m = obstacleGrid.size();
        int n = obstacleGrid[0].size();
        vector<vector<int>>dp(m,vector<int>(n,0));
        //初始化跳过障碍物及其后续位置
        for(int i = 0;i < m&&obstacleGrid[i][0] == 0;i++) dp[i][0] = 1;
        for(int i = 0;i < n&&obstacleGrid[0][i] == 0;i++) dp[0][i] = 1;
        for(int i = 1;i < m;i++){
            for(int j = 1;j < n;j++){
                if(obstacleGrid[i][j]==1) continue;//跳过障碍
                dp[i][j] = dp[i-1][j]+dp[i][j-1];
            }
        }
        return dp[m-1][n-1];
    }
};

结果

相关推荐
for_ever_love__2 小时前
Objective-C学习 类别和扩展
学习·算法·objective-c
Sakinol#2 小时前
Leetcode Hot 100 ——回溯part02
算法·leetcode
ArturiaZ2 小时前
【day53】
开发语言·c++·算法
历程里程碑2 小时前
36 Linux线程池实战:日志与策略模式解析
开发语言·数据结构·数据库·c++·算法·leetcode·哈希算法
可编程芯片开发2 小时前
基于自适应MUSIC算法的波束形成matlab仿真
算法·matlab·波束形成·自适应music
2301_789015622 小时前
DS进阶:红黑树
c语言·开发语言·数据结构·c++·算法·r-tree·lsm-tree
郝学胜-神的一滴2 小时前
深度学习浪潮:解锁技术边界与产业新图景
数据结构·人工智能·python·深度学习·算法
daxi1502 小时前
C语言从入门到进阶——第13讲:深入理解指针(3)
c语言·开发语言·数据结构·算法
white-persist2 小时前
【CTF线下赛 AWD】AWD 比赛全维度实战解析:从加固防御到攻击拿旗
网络·数据结构·windows·python·算法·安全·web安全