美文网首页
无重复字符的最长子串(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