LeetCode Hot100 11~20

目录

  • 子串
    • [11. 滑动窗口最大值](#11. 滑动窗口最大值)
    • [12. 最小覆盖子串](#12. 最小覆盖子串)
  • 数组
    • [13. 最大子数组和](#13. 最大子数组和)
    • [14. 合并区间](#14. 合并区间)
    • [15. 翻转数组](#15. 翻转数组)
    • [16. 除数字自身以外的乘积](#16. 除数字自身以外的乘积)
    • [17. 缺失的第一个正数](#17. 缺失的第一个正数)
  • 矩阵
    • [18. 矩阵置零](#18. 矩阵置零)
    • [19. 螺旋矩阵](#19. 螺旋矩阵)
    • [20 旋转图像90度](#20 旋转图像90度)

子串

11. 滑动窗口最大值

本题使用deque来维护一个单调队列 注意删除元素和添加元素的时机即可

cpp 复制代码
class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        vector<int> ans;
        deque<int> dq;

        // 我们首先将前面K个数字加进去
        for (int i = 0; i < k; i++) {    
            while(!dq.empty() && nums[i] > dq.back()) {
                dq.pop_back();
            }

            dq.push_back(nums[i]);
        }
        ans.push_back(dq.front());

        for (int i = k; i < nums.size(); i++) {
            if (nums[i - k] == dq.front()) {
                dq.pop_front();
            }

            while(!dq.empty() && nums[i] > dq.back()) {
                dq.pop_back();
            }

            dq.push_back(nums[i]);
            ans.push_back(dq.front());
        }
        return ans;
    }
};

12. 最小覆盖子串

类似滑动窗口问题 再加上一个欠账表就可以解决 类似前面的最小子数组问题

cpp 复制代码
public:
    string minWindow(string s, string t) {
        unordered_map<char , int> unmapBill;
        for (auto ch : t) {
            unmapBill[ch]++;
        }
        int lnBill = t.size();

        int L = 0;
        int R = 0;
        int minL = 0;
        int minR = 0;
        int minWin = INT_MAX;

        while (R < s.size()) {
            if (unmapBill.count(s[R])) {
                if (unmapBill[s[R]] > 0) {
                    lnBill--;
                }
                unmapBill[s[R]]--;
            }

            while(lnBill == 0) {
                if ((R - L) < minWin) {
                    minL = L;
                    minR = R;
                    minWin = R - L;
                }

                if (unmapBill.count(s[L])) {
                    unmapBill[s[L]]++;
                    if (unmapBill[s[L]] > 0) {
                        lnBill++;
                    }
                }

                L++;
            }

            R++;
        }

        if(minWin == INT_MAX) {
            return "";
        }

        string ans = s.substr(minL , minWin + 1);
        return ans;
    }
};

数组

13. 最大子数组和

很简单的动态规划

cpp 复制代码
class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        vector<int> dp(nums.size() , 0);
        dp[0] = nums[0];
        for (int i = 1; i < nums.size(); i++) {
            if (dp[i-1] < 0) {
                dp[i] = nums[i];
            }else {
                dp[i] = dp[i-1] + nums[i];
            }
        }

        int lnmax = dp[0];
        for (auto x : dp) {
            if (x > lnmax) {
                lnmax = x;
            }
        }

        return lnmax;
    }
};

14. 合并区间

很简单的贪心问题 需要注意的是

  1. 我们如果要降序排序 第一个元素要小于第二个元素
  2. 合并区间的时候要注意右边界
cpp 复制代码
            bool compare(vector<int>& v1 , vector<int>& v2) {
            if (v1[0] != v2[0]) {
                return v1[0] < v2[0];
            }else {
                return v1[0] < v2[0];
            }
        }
class Solution {
public:


    vector<vector<int>> merge(vector<vector<int>>& intervals) {
        if (intervals.size() == 1) {
            return intervals;
        }

        vector<vector<int>> ans;
        
        sort(intervals.begin() , intervals.end() , compare);
        ans.push_back(intervals[0]);
        for (int i = 1; i < intervals.size(); i++) {
            if (intervals[i][0] <= ans.back()[1]) {
                int R = max(intervals[i][1] , ans.back()[1]);
                ans.back()[1] = R;
            }else {
                ans.push_back(intervals[i]);
            }
        }

        return ans;
    }
};

15. 翻转数组

很简单的一个脑筋急转弯 需要注意 beigin() 到 end() 是左闭右开

cpp 复制代码
class Solution {
public:
    void rotate(vector<int>& nums, int k) {
        int n = nums.size();
        k = k % n;  // 确保k小于数组的大小

        reverse(nums.begin(), nums.end());  // 翻转整个数组
        reverse(nums.begin(), nums.begin() + k);  // 翻转前k个元素
        reverse(nums.begin() + k, nums.end());  // 翻转剩余元素
    }
};

16. 除数字自身以外的乘积

这道题属于是知道了前后缀积就简单 前后缀积相乘就能得到答案

cpp 复制代码
class Solution {
public:
    vector<int> productExceptSelf(vector<int>& nums) {
        // 前缀 后缀积
        vector<int> vPre(nums.size(), 1);
        vector<int> vSub(nums.size(), 1);
        vector<int> ans(nums.size() , 0);

        for (int i = 1; i < nums.size(); i++) {
            vPre[i] = vPre[i-1] * nums[i-1];
        }

        for (int i = nums.size() - 2 ; i >= 0 ; i--) {
            vSub[i] = vSub[i+1] * nums[i + 1];
        }

    
        for (int i = 0; i < nums.size() ;i++) {
            int lnans = vPre[i] * vSub[i];
            ans[i] = lnans;
        }

        return ans;
    }
};

17. 缺失的第一个正数

如果能用哈希表就用哈希表

不能的话就在原数组上交换

需要注意三点

  1. 交换的条件
  2. 避免重复 进入死循环
  3. 最后ans = I + 1;
cpp 复制代码
class Solution {
public:
    int firstMissingPositive(vector<int>& nums) {
        int n = nums.size();
        for (int i = 0; i < nums.size(); i++) {
            while(nums[i] > 0 && nums[i] <= n && nums[i] != nums[nums[i] - 1]) {
                swap(nums[i] , nums[nums[i] - 1]);
            }
        }

        int ans = n + 1;
        for (int i = 0; i < nums.size(); i++) {
            if (nums[i] != i + 1) {
                ans = i + 1;
                break;
            }
        }

        return ans;
    }
};

矩阵

18. 矩阵置零

使用第一行第一列来进行标记

在更新的时候要从第一行 第一列开始 避免破坏我们之前记录的值

cpp 复制代码
class Solution {
public:
    void setZeroes(vector<vector<int>>& matrix) {
        // 行列记录 行标列标
        int m = matrix.size(); 
        int n = matrix[0].size();
        bool cow = false;
        bool rol = false;

        for (int i = 0 ; i < m ; i++) {
            for (int j = 0; j < n; j++) {
                if (matrix[i][j] == 0) {
                    
                    if (i == 0) {
                        cow = true;
                    }
                    if (j == 0) {
                        rol = true;
                    }
                    matrix[i][0] = 0;
                    matrix[0][j] = 0;
                }
            }
        }

        for (int i = 1; i < m; i++) {
            for (int j = 1 ; j < n; j++) {
                if (matrix[0][j] == 0 || matrix[i][0] == 0) {
                    matrix[i][j] = 0;
                }
            }
        }

        for (int i = 0; i < m; i++) {
            if (rol) {
                matrix[i][0] = 0;
            }
        }

        for (int j = 0; j < n; j++) {
            if (cow) {
                matrix[0][j] = 0;
            }
        }
    }
};

19. 螺旋矩阵

只需要设置四个变量 然后四个方向依次遍历即可

cpp 复制代码
#include <vector>
using namespace std;

class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        vector<int> ans;
        int m = matrix.size();       // 行数
        int n = matrix[0].size();    // 列数
        int left = 0, right = n - 1, top = 0, bottom = m - 1;

        while (left <= right && top <= bottom) {
            // 从左到右
            for (int i = left; i <= right; i++) {
                ans.push_back(matrix[top][i]);
            }
            top++;

            // 从上到下
            for (int i = top; i <= bottom; i++) {
                ans.push_back(matrix[i][right]);
            }
            right--;
            // 从右到左
            if (top <= bottom) {
                for (int i = right; i >= left; i--) {
                    ans.push_back(matrix[bottom][i]);
                }
            }
            bottom--;

            //从下到上
            if (left <= right) {
                for (int i = bottom; i >= top; i--) {
                    ans.push_back(matrix[i][left]);
                }
            }
            left++;
        }
        return ans;
    }
};

20 旋转图像90度

记住公式 先上下翻转 再对角线翻转

上下翻转的时候注意 小于 N/2

cpp 复制代码
class Solution {
public:
    void rotate(vector<vector<int>>& matrix) {
        int n = matrix.size() ;
        // 上下翻转
        for (int i = 0; i < n / 2; i++) {
            swap(matrix[i] , matrix[n - i - 1]);
        }

        // 对角线反转
        for (int i = 0; i < matrix.size(); i++) {
            for (int j = i; j < matrix[0].size(); j++) {
                swap(matrix[i][j] , matrix[j][i]);
            }
        }
    }
};
相关推荐
LCG元1 小时前
【面试问题】JIT 是什么?和 JVM 什么关系?
面试·职场和发展
XH华3 小时前
初识C语言之二维数组(下)
c语言·算法
南宫生4 小时前
力扣-图论-17【算法学习day.67】
java·学习·算法·leetcode·图论
不想当程序猿_4 小时前
【蓝桥杯每日一题】求和——前缀和
算法·前缀和·蓝桥杯
落魄君子4 小时前
GA-BP分类-遗传算法(Genetic Algorithm)和反向传播算法(Backpropagation)
算法·分类·数据挖掘
菜鸡中的奋斗鸡→挣扎鸡4 小时前
滑动窗口 + 算法复习
数据结构·算法
Lenyiin4 小时前
第146场双周赛:统计符合条件长度为3的子数组数目、统计异或值为给定值的路径数目、判断网格图能否被切割成块、唯一中间众数子序列 Ⅰ
c++·算法·leetcode·周赛·lenyiin
郭wes代码4 小时前
Cmd命令大全(万字详细版)
python·算法·小程序
scan7245 小时前
LILAC采样算法
人工智能·算法·机器学习
菌菌的快乐生活5 小时前
理解支持向量机
算法·机器学习·支持向量机