LeetCode 实践练习76-80

LeetCode—76(最小覆盖子串)

在这里插入图片描述
方法:在这里插入图片描述
第一种解决办法是用HashMap,而不是HashSet,因为要统计T串中字母的个数,而不是仅仅看某个字母是否在T串中出现。统计好T串字母的个数后,就开始遍历S串,对于S中的每个遍历到的字母,都在HashMap中的映射值减一。如果减一后的映射值仍然大于等于0,则T串中存在,我们使用计数器自增1,当计数器=T.size()时,说明窗口已经包含了T中的所有字母。此时更新一个minLen和结果res,这里的minLen是我们维护的一个全局变量,用来记录出现过的包含T串所有字母的最短的子串的长度,结果res就是这个最短的子串。然后我们要开始收缩左边界,由于我们遍历的时候,对映射值减了1,所以此时去除字母的时候,就要把减去的1加回来,此时如果加1后的值大于0了,说明此时我们少了一个T中的字母,那么cnt值就要减1了,然后移动左边界left。那么你可能会疑问,对于不在T串中的字母的映射值也这么加呀减呀的,真的大丈夫(带胶布)吗?其实没啥事,因为对于不在T串中的字母,我们减1后,变-1,cnt不会增加,之后收缩左边界的时候,映射值加1后为0,cnt也不会减少,所以并没有什么影响啦。
C++代码:

class Solution {
public:
    string minWindow(string s, string t) {
        string res = "";
        unordered_map<char, int> letterCnt;
        int left = 0, cnt = 0, minLen = INT_MAX;
        for (char c : t) ++letterCnt[c];
        for (int i = 0; i < s.size(); ++i) {
            if (--letterCnt[s[i]] >= 0) ++cnt;
            while (cnt == t.size()) {
                if (minLen > i - left + 1) {
                    minLen = i - left + 1;
                    res = s.substr(left, minLen);
                }
                if (++letterCnt[s[left]] > 0) --cnt;
                ++left;
            }
        }
        return res;
    }
};

第二种:这道题也可以不用HashMap,直接用个int的数组来代替,因为ASCII只有256个字符,所以用个大小为256的int数组即可代替HashMap,但由于一般输入字母串的字符只有128个,所以也可以只用128,其余部分的思路完全相同,虽然只改了一个数据结构,但是运行速度提高了一倍,说明数组还是比HashMap快啊。
C++代码:

class Solution {
public:
    string minWindow(string s, string t) {
        string res = "";
        vector<int> letterCnt(128, 0);
        int left = 0, cnt = 0, minLen = INT_MAX;
        for (char c : t) ++letterCnt[c];
        for (int i = 0; i < s.size(); ++i) {
            if (--letterCnt[s[i]] >= 0) ++cnt;
            while (cnt == t.size()) {
                if (minLen > i - left + 1) {
                    minLen = i - left + 1;
                    res = s.substr(left, minLen);
                }
                if (++letterCnt[s[left]] > 0) --cnt;
                ++left;
            }
        }
        return res;
    }
};

LeetCode—77(组合)

在这里插入图片描述
方法:深度优先搜索DFS解,建立一个res来保存结果的最大集合。还要定义一个保存每个小集合的out,每次放一个数到out里,如果out里数个数到了k个,则把out保存到最终结果中,否则在下一层继续调用递归。
C++代码:

class Solution {
public:
    vector<vector<int>> combine(int n, int k) {
        vector<vector<int>> res;
        vector<int> out;
        helper(n,k,1,out,res);//这里的1为level,即现在数字到哪了,只能往上取
        return res;
    }
    void helper(int n,int k,int level,vector<int>& out,vector<vector<int>>& res){
        if(out.size() == k) {res.push_back(out);return;}
        for(int i = level;i <= n;i++){//此处要等于,考虑完全
            out.push_back(i);
            helper(n,k,i+1,out,res);
            out.pop_back();
        }
    }
};

解法二:利用性质 C(n, k) = C(n-1, k-1) + C(n-1, k),一直拆分。(还没看懂)
C++代码:

class Solution {
public:
    vector<vector<int>> combine(int n, int k) {
        if (k > n || k < 0) return {};
        if (k == 0) return {{}};
        vector<vector<int>> res = combine(n - 1, k - 1);
        for (auto &a : res) a.push_back(n);
        for (auto &a : combine(n - 1, k)) res.push_back(a);
        return res;
    }
};

LeetCode—78(子集)

在这里插入图片描述
方法:跟上一题思路差不多,区别是每次把递归的结果都保存入res中。
C++代码:(不够精简)

class Solution {
public:
    vector<vector<int>> subsets(vector<int>& nums) {
        vector<vector<int>> res;
        vector<int> out;
        int d = nums.size();
        helperDFS(nums,d,0,res,out);//从零开始,与上一题不同
        return res;
    }
    void helperDFS(vector<int>& nums,int d,int level,vector<vector<int>>& res,vector<int>& out){
        res.push_back(out);
        for(int i = level;i < d;i++){
            out.push_back(nums[i]);
            helperDFS(nums,d,i+1,res,out);
            out.pop_back();
        }
    }
};

LeetCode—79(单词搜索)

在这里插入图片描述
方法:这道题典型的深度优先遍历DFS的应用
C++代码:

class Solution {
public:
    bool exist(vector<vector<char>>& board, string word) {
        if(board.empty() || board[0].empty()) return false;
        int m = board.size(),n = board[0].size();
        vector< deque<bool> > visited(m, deque<bool>(n,false));
        for(int i = 0;i < m;i++){
            for(int j = 0;j < n;j++){
                if(search(board,word,visited,i,j,0)) return true;
            }
        }
        return false;
    }
    bool search(vector<vector<char>>& board,string word,vector<deque<bool>>& visited,int i,int j,int idx){
        if(idx == word.size()) return true;
        int m = board.size(),n = board[0].size();
        if(i < 0 || j < 0 || i >= m || j >= n || visited[i][j] || board[i][j] != word[idx]) return false;
        visited[i][j] = true;
        bool res = search(board,word,visited,i+1,j,idx+1)
                || search(board,word,visited,i-1,j,idx+1)
                || search(board,word,visited,i,j+1,idx+1)
                || search(board,word,visited,i,j-1,idx+1);
        visited[i][j] = false;//这步很重要;记住
        return res;
    }
};

LeetCode—80(删除排序数字中的重复项II)

在这里插入图片描述
方法:此题与26题及其相似,都是利用快慢指针。26题是每个元素只出现一次,而本题是两次,所以需要一个count进行计数。
C++代码:

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        if(nums.size() <= 2) return nums.size();//很重要跟上一题的判断条件不一样了
        int pre = 0,cur = 1,n = nums.size(),count = 1;//此处cur也为1
        while(cur < n){
            if(nums[pre] == nums[cur] && count == 0) ++cur;
            else{
                if(nums[pre] == nums[cur]) --count;
                else count = 1;
                nums[++pre] = nums[cur++];
            }
        }
        return pre+1;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值