无重复字符的最长子串

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

  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,这就否定了我们原来的假设,得出矛盾,因此命题得证,即:
      如果以s[i]为结尾的最长无重复字符的子串起始位置为j,那么当s[i]遍历到下一个位置s[i + 1]时,此时最长无重复字符的子串起始位置J一定在j的右边或者保持j位置不变
    • 因此,这样就将我们算法的时间复杂度降低了一维,在进行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 ) O(n) O(n)

要用到了双指针算法+哈希表知识点,通过分析发现首指针j不会向左移动,因此时间复杂度降为 O ( n ) O(n) O(n)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

KevinHQK

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

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

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

打赏作者

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

抵扣说明:

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

余额充值