leetcode热题100刷题日记(3)

72.编辑距离

在这里插入图片描述

思路

编辑距离是一个很经典的动态规划的问题,其难点在于状态的定义,在此题中,需要一个二维的dp数组,dp[i][j] 表示 s1 的前 i 个字母和 s2 的前 j 个字母之间的编辑距离。

而状态转移方程的确定,也需要分情况谈论:

1. 当s1[i-1]==s2[j-1],因为下标从0开始,所以实际上是s1的第i个字符和s2的第j个字符相等,那么此时这两个字符不需要变换,所以 dp[i][j]=dp[i-1][j-1];
2. 当s1[i-1]!=s2[j-1],也就是s1的第i个字符和s2的第j个字符不相等,那么有三种做法:

  • 将s1的前i-1个字符编辑成s2的前j个,再把s1的第i个字符删除
  • 将s1的前i个字符编辑成s2的前j-1个,再添加一个和s2[j]一样的字符
  • 将s1的前i-1个字符编辑成s2的前j-1个,再将s1[i]替换成s2[j]

所以,就有了状态转移方程:

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

代码

class Solution {
public:
    int minDistance(string s1, string s2) {
        int m = s1.size();
        int n = s2.size();
        int dp[m+1][n+1];
        for (int i = 0; i < m+1; i++) dp[i][0] = i;
        for (int i = 0; i < n+1; i++) dp[0][i] = i;

        for (int i = 1; i < m+1; i++){
            for (int j = 1; j < n+1; j++){
                if (s1[i-1] == s2[j-1]){
                    dp[i][j] = dp[i-1][j-1];
                } else{
                    dp[i][j] = min(min(dp[i-1][j] + 1, dp[i][j-1] + 1), dp[i-1][j-1] + 1);
                }
            }
        }

        return dp[m][n];
    }
};

75.颜色分类

在这里插入图片描述

思路

此题也是一个经典题目,称为荷兰国旗问题

我们用三个指针(p0, p2 和curr)来分别追踪0的最右边界,2的最左边界和当前考虑的元素。

While cur <= p2 :
若 nums[cur] = 0 :交换第 curr个 和 第p0个 元素,并将指针都向右移
若 nums[cur] = 2 :交换第 curr个和第 p2个元素,并将 p2指针左移
若 nums[cur] = 1 :将指针curr右移

这里有一个容易疏忽的细节,就是当nums[cur]==2的时候,交换位置以后,cur是不自增的,因为p2位置上的元素还是没有检查过的,而由于p0始终在cur左边或者等于cur,所以当nums[cur]==0,交换位置时,p0的位置已经被cur检查过了,只能是0或者1,因此交换以后cur直接自增。

代码

class Solution {
public:
    void sortColors(vector<int>& nums) {
        int p0=0,p2=nums.size()-1;
        int cur=0;
        while(cur<=p2){
            if(nums[cur]==2)
            //这里的cur还没有检查过,不能自增
                swap(nums[cur],nums[p2--]);
            else if(nums[cur]==0)
                swap(nums[cur++],nums[p0++]);
            else
                cur++;
        }
    }
};

76.最小覆盖子串

在这里插入图片描述

思路

这道题是这些天来遇到的比较难的一道,要用到滑动窗口的思想,详见大佬的题解

代码

class Solution {
public:
    string minWindow(string s, string t) {
    // 记录最短子串的开始位置和长度
    int start = 0, minLen = INT_MAX;
    int left = 0, right = 0;
    
    unordered_map<char, int> window;
    unordered_map<char, int> needs;
    for (char c : t) needs[c]++;
    
    int match = 0;
    
    while (right < s.size()) {
        char c1 = s[right];
        //count方法,如果有返回1,否则返回0
        if (needs.count(c1)) {
            window[c1]++;
            if (window[c1] == needs[c1]) 
                match++;
        }
        right++;
        
        while (match == needs.size()) {
            if (right - left < minLen) {
                // 更新最小子串的位置和长度
                start = left;
                minLen = right - left;
            }
            char c2 = s[left];
            if (needs.count(c2)) {
                window[c2]--;
                if (window[c2] < needs[c2])
                    match--;
            }
            left++;
        }
    }
    return minLen == INT_MAX ?
                "" : s.substr(start, minLen);
}
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值