leetcode做题方法总结

1 滑动窗口法

例题:209. 长度最小的子数组https://leetcode-cn.com/problems/minimum-size-subarray-sum/(找出满足>=target的最小子数组)

思路:用两个指针(类似于快慢指针)。不满足就右移r指针,直到满足为止,满足了就左移l指针,直到不满足为止。

法一:单循环,每次只移动一个指针,满足移左,不满足移右。

这个方法时间用得比法二少,但是代码量更多,因为需要单独处理第一个元素(否则如果第一个元素已经满足了要求,第一次循环就会把左指针往右移一位,导致左指针到了右指针的右边)。

class Solution {
public:
    int minSubArrayLen(int target, vector& nums) {
        int n=nums.size();
        if(n==0)return 0;
        int left=0,right=0,total=nums[0];
        int min_len=INT_MAX;
        if(total>=target)return 1;
        while(right=target){
                total-=nums[left];
                min_len=min_len

法二:循环嵌套,外层循环只负责移动右指针,右指针移到满足条件后就用内层循环移动左指针,移到不满足为止。

class Solution {
public:
    int minSubArrayLen(int target, vector& nums) {
        int n=nums.size();
        if(n==0)return 0;
        int min_len=INT_MAX,left=0,right=0,total=0;
        while(right=target){
                min_len=min(min_len,right-left+1);
                total-=nums[left];
                left++; 
            }
            right++;
        }
        return min_len==INT_MAX?0:min_len;

    }
};

2 双指针法

1 同向

例题:27. 移除元素https://leetcode-cn.com/problems/remove-element/( 原地 移除数组中所有等于 val 的元素,并返回移除后数组的新长度。)

思路:快指针负责遍历,慢指针负责存储新的数组。

class Solution {
public:
    int removeElement(vector& nums, int val) {
        int black=0;
        int i;
        for(i=0;i

2 反向

例题:977. 有序数组的平方https://leetcode-cn.com/problems/squares-of-a-sorted-array/(非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序)

思路:左右指针负责对比两边端点的平方,不断找出最大的平方。指针也可以从中间分界处开始往两边移动,负责找出最小的平方,这样会多一步找分界点。

注意:要考虑左(右)指针移到底的情况,就本题而言考虑只有负(正)数的情况。

class Solution {
public:
    vector sortedSquares(vector& nums) {
        int n=nums.size(),tem;
        vector result(n,0);
        int left=0,right=n-1,site=n-1;
        for(int i=0;inums[right]){
                result[site--]=nums[left++];
            }
            else {
                result[site--]=nums[right--];
            }
        }
        return result;
    }
};

3 有一知二

如果要对两个数组进行共同操作,可以思考能不能有一个数组的操作结果推出另一个数组的操作结果,如果可以且不麻烦,那就可以把两个数组的问题转换为一个数组的问题。

例题:
 

4.寻找两个正序数组的中位数_Eaco1412的博客-CSDN博客https://blog.csdn.net/qq_45520030/article/details/123404773

4 矩阵快速幂

  • 如果一个问题可与转化为求解一个矩阵的 nnn 次方的形式,那么可以用快速幂来加速计算
  • 如果一个递归式形如 f(n)=\sum_{i=1}^{m}a_{i}f(n-i),即齐次线性递推式,我们就可以把数列的递推关系转化为矩阵的递推关系,即构造出一个矩阵的 n 次方乘以一个列向量得到一个列向量,这个列向量中包含我们要求的 f(n)。一般情况下,形如 f(n)=\sum_{i=1}^{m}a_{i}f(n-i)​可以构造出这样的 m×m 的矩阵:

\left[ \begin{matrix} a_1 & a_2 & a_3 & \cdots & a_m \\ 1 & 0 & 0 & \cdots & 0 \\ 0 & 1 & 0 & \cdots & 0 \\ 0 & 0 & 1 & \cdots & 0 \\ \vdots & \vdots & \vdots & \ddots & \vdots \\ 0 & 0 & 0 & \cdots & 1 \\ \end{matrix} \right]

  • 那么遇到非齐次线性递推我们是不是就束手无策了呢?其实未必。有些时候我们可以把非齐次线性递推转化为其次线性递推,比如这样一个递推:

 f(x)=(2x-6)c+f(x-1)+f(x-2)+f(x-3)

我们可以做这样的变换:

f(x)+xc=[f(x-1)+(x-1)c]+[f(x-2)+(x-2)c]+[f(x-3)+(x-3)c]

g(x)=f(x)+xc,那么我们又得到了一个齐次线性递:

g(x)=g(x-1)+g(x-2)+g(x-3)

于是就可以使用矩阵快速幂求解了。当然并不是所有非齐次线性都可以化成齐次线性,我们还是要具体问题具体分析。

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/climbing-stairs/solution/pa-lou-ti-by-leetcode-solution/
来源:力扣(LeetCode)

例题:

70. 爬楼梯_Eaco1412的博客-CSDN博客https://blog.csdn.net/qq_45520030/article/details/123435749

5 矩阵动态规划

例题:72. 编辑距离

如果我们有单词 A 和单词 B,可以执行以下操作:

  • 在单词 A 中插入一个字符:如果我们知道 horse 到 ro 的编辑距离为 a,那么显然 horse 到 ros 的编辑距离不会超过 a + 1。这是因为我们可以在 a 次操作后将 horse 和 ro 变为相同的字符串,只需要额外的 1 次操作,在单词 A 的末尾添加字符 s,就能在 a + 1 次操作后将 horse 和 ro 变为相同的字符串;
  • 在单词 B 中插入一个字符(等同于把A删去一个字符):如果我们知道 hors 到 ros 的编辑距离为 b,那么显然 horse 到 ros 的编辑距离不会超过 b + 1,原因同上;
  • 修改单词 A 的一个字符:如果我们知道 hors 到 ro 的编辑距离为 c,那么显然 horse 到 ros 的编辑距离不会超过 c + 1,原因同上。

我们按此规则可以继续拆分,直到:

  • 字符串 A 为空,从“”转换到 “ro”,显然编辑距离为字符串 B 的长度,这里是 2;
  • 字符串 B 为空,如从“horse”转换到“”,显然编辑距离为字符串 A 的长度,这里是 5。

至此,可以得到以其中一串为空这种情况为边界的矩阵动态规划。

若 A 的第i个字母和 B 的第j个字母相同:

D[i][j]=min(D[i-1][j]+1,D[i][j-1]+1,D[i-1][j-1])

若 A 的第i个字母和 B 的第j个字母不同:

D[i][j]=min(D[i-1][j]+1,D[i][j-1]+1,D[i-1][j-1]+1)

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/edit-distance/solution/bian-ji-ju-chi-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

你可能感兴趣的:(leetcode,leetcode,算法)