机考刷题之 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];
    }
};

结果

相关推荐
啦啦啦_99991 分钟前
1. 线性回归之 导数偏导数
算法·矩阵·线性回归
踩坑记录3 分钟前
leetcode hot100 5. 最长回文子串 中心扩展法 medium
leetcode
雨季mo浅忆19 分钟前
模拟面试梳理
面试·职场和发展
itzixiao23 分钟前
L1-058 6翻了(15分)[java][python]
java·开发语言·python·算法
念何架构之路24 分钟前
数组和切片实战
数据结构·算法·排序算法
重生之我是Java开发战士26 分钟前
【数据结构】AVL树解析
数据结构·算法
小π军29 分钟前
STL之multiset 常见API介绍
数据结构·c++·算法
踩坑记录29 分钟前
leetcode hot100 1143. 最长公共子序列 mediuim 递归优化
leetcode
研究点啥好呢31 分钟前
Momenta算法工程师面试题精选:10道高频考题+答案解析
人工智能·算法·求职招聘·面试笔试
Resistance丶未来31 分钟前
DeepSeek-V4 新手快速上手指南
数据结构·python·gpt·算法·机器学习·claude·claude 4.6