美文网首页
无重复字符的最长子串(leetcode 3)

无重复字符的最长子串(leetcode 3)

作者: 韩其凯 | 来源:发表于2023-02-06 10:17 被阅读0次
    1. 题意

    1. 分析:

      • 我们可以将所给的长度为n的字符串,对串中的每一个字符,求得以该字符为结尾的最长无重复字符的子串。所有字串长度的最大值,便是要寻找的答案。
      • 如果以s[i]为结尾的最长无重复字符的子串起始位置为j,那么当s[i]遍历到下一个位置s[i + 1]时,此时最长无重复字符的子串起始位置J一定在j的右边或者保持j位置不变,一定不会出现在j的左边。可以通过反证法来证明,倘若当s[i]遍历到下一个位置s[i + 1]时,最长无重复字符的子串起始位置J在j的左边,那么在s[i]还没有遍历到s[i + 1]这个字符的时候,最长无重复字符子串的起始位置一定也在j的左边而非j,这就否定了我们原来的假设,得出矛盾,因此命题得证,即:
        <font color="#660000">如果以s[i]为结尾的最长无重复字符的子串起始位置为j,那么当s[i]遍历到下一个位置s[i + 1]时,此时最长无重复字符的子串起始位置J一定在j的右边或者保持j位置不变</font><br />
      • 因此,这样就将我们算法的时间复杂度降低了一维,在进行j位置的搜索时,直接从上一状态向右搜索即可。
    2. 代码:
      C++代码:

    class Solution {
    public:
        int lengthOfLongestSubstring(string s) {
            unordered_map<char, int> hash; // 建立哈希表(使用unordered_map<char,int> int字段默认初始化为0)
            int res = 0; // 定义答案
            for (int i = 0, j = 0; i < s.size(); i++){
                hash[s[i]] ++;  // 把s[i + 1]加入哈希表,此时,如果出现了重复字符,那么hash[s[i]]的值会变成2。
                while(hash[s[i]] > 1)   hash[s[j++]]--;
                /*
                hash[s[j++]]--;
                这句话的意义在于,当我们发现了重复字符s[i]之后,那么从j位置起,将hash[s[j]]的值减1,并且将j的值增加1,直到我们找到了重复的字符串,结束循环。
                拿字符串“zuabca”来说,当遍历到第二个‘a’时,此时i=3,j=0,
                (1)将hash[s[j]]的值减1,目的是为了删除重复的字符;
                (2)将j的值加1(右移),目的是为了计算最长无重复字符子串的长度;
                我们会发现,这样进行的话,会将hash['z'], hash['u']的值也给减1了,我们本想将重复字符‘a’的hash值变成1,即hash['a'] == 1,但是此时出现了这样的结果:hash['z'] == hash['u'] == 0,hash['a'] == 1。
                这样的话,对我们解题来说,无所谓!因为前面推导出j是单调向右的,不会再向左了,第一个‘a’的左边的hash['z'], hash['u']变成什么样子,我们都不再去用它了。
                */
                res = max(res, i - j + 1);  // 找到所有子串的最大值,即为最终结果。
            }
            return res;
        }
    };
    

    Python代码:

    class Solution:
        def lengthOfLongestSubstring(self, s: str) -> int:
            Hash = dict()
            j, res = 0, 0
            for i in range(len(s)):
                Hash[s[i]] = Hash[s[i]] + 1 if s[i] in Hash else 1
                while Hash[s[i]] > 1:
                    Hash[s[j]] -= 1
                    j += 1
                res = max(res, i - j + 1)
            return res
    
    1. 总结:
      • 本题主要用到了双指针算法+哈希表知识点,通过分析发现首指针j不会向左移动,因此时间复杂度降为O(n)

    相关文章

      网友评论

          本文标题:无重复字符的最长子串(leetcode 3)

          本文链接:https://www.haomeiwen.com/subject/gictkdtx.html