leetcode刷题2———子串系列

1.无重复字符的最长子串
给定一个字符串,请你找出其中不含有重复字符的最长子串的长度。
考察知识点:哈希表,滑动窗口

class Solution {
public:
//i表示字串起始位置,j表示子串终止位置。当未出现重复时,字符串的长度即为字符串的结束位置减去起始位置。
//出现重复时,重复字符位置如果在原起始位置前,则起始位置不用更新;如果在原起始位置后,则用重复字符的位置去更新起始位置。
    int lengthOfLongestSubstring(string s) {
        int maxlen=0;
        unordered_map<char,int> mp;
        for(int i=0,j=0;j<s.size();++j)
        {
            if(mp.count(s[j])>0)
            {
                i=max(i,mp[s[j]]);
            }
            maxlen=max(maxlen,j-i+1);
            mp[s[j]]=j+1; //*
        }
        return maxlen;
    }
};

2.最长回文子串
给你一个字符串 s,找到 s 中最长的回文子串。
考察知识点:动态规划
用 P(i,j)表示字符串s的第i到第j个字母组成的串是否为回文串,状态转移方程为
在这里插入图片描述

class Solution {
public:
    string longestPalindrome(string s) {
        vector<vector<int>> dp(s.length(), vector<int>(s.length()));
        string ans;
        for (int L = 0; L < s.length(); ++L)
         {
            for (int i = 0; i + L < s.length(); ++i) 
            {
                int j = i + L;
                if (L == 0)  dp[i][j] = 1;
                else if (L == 1)  dp[i][j] = (s[i] == s[j]);
                else  dp[i][j] = (s[i] == s[j] && dp[i + 1][j - 1]);
                
                if (dp[i][j] && L + 1 > ans.length()) 
                    ans = s.substr(i, L + 1);             
            }
        }
        return ans;
    }
};

3.串联所有单词的子串
给定一个字符串 s 和一些长度相同的单词 words。找出 s 中恰好可以由 words 中所有单词串联形成的子串的起始位置。注意子串要与 words 中的单词完全匹配,中间不能有其他字符,但不需要考虑 words 中单词串联的顺序。
考察知识点:哈希表

class Solution {
public:
    vector<int> findSubstring(string s, vector<string>& words) {
        if(s.size()==0||words.size()==0)    return {};
        int m=words.size(),n=words[0].size();
        if(s.size()<m*n)    return {};
        unordered_map<string,int> mp,tmp;
        for(int i=0;i<m;++i)
            ++mp[words[i]];
        vector<int> v;
        for(int i=0;i+m*n<=s.size();++i)
        {
            int j=i;
            for(;j<i+m*n;j+=n)
            {
                string str=s.substr(j,n);
                if(mp.find(str)==mp.end()) break;
                ++tmp[str];
            }
            if(j==i+m*n&&tmp==mp)
            	v.push_back(i);
        }
        return v;
    }
};

4.覆盖最小子串
给你一个字符串s 、一个字符串t 。返回s中涵盖t所有字符的最小子串。如果 s 中不存在涵盖t所有字符的子串,则返回空字符串 。注意:如果s中存在这样的子串,我们保证它是唯一的答案。
考察知识点:哈希表、滑动窗口

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

思路:
(1)用哈希表完成,由于匹配数组t可能存在重复值,所以map数值需要是int。
总体算法模拟音乐音量上下浮动,t 的元素个数就是音量高度,t 以外的其他元素都为 0,
(2)遍历 s 的过程中,遇到一个音则将其减少一个音量.(* t 数组以外的音量不可能大于 0)
搜索过程中,指定音量下降计数 cnt 增加,减小到 0 以下不算在内,
当减少总数等于 t 的总数时,所有数就齐了,计算长度。
(3)随后进行回退,如果是 t 以外的音,其增加不改变计数 cnt,直到遇到 t 中的音,
且该值在map中大于0时(区间中 t 的某一个音大于其原始的数量,它map的值可能会小于0???),
回退停止,继续向前搜索,重复 步骤 2。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

给算法爸爸上香

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值