每周LeetCode算法题(一):Longest Substring Without Repeating Characters

每周LeetCode算法题(一)

题目: 3. Longest Substring Without Repeating Characters

Given a string, find the length of the longest substring without repeating characters.

Examples:

Given “abcabcbb”, the answer is “abc”, which the length is 3.

Given “bbbbb”, the answer is “b”, with the length of 1.

Given “pwwkew”, the answer is “wke”, with the length of 3. Note that the answer must be a substring, “pwke” is a subsequence and not a substring.

解法分析

这道题乍一看,第一反应可能会是,以字符串str中每一个字母为第一个字符str[i],然后向后依次j++检测后面每一个的字符str[j]是否与i到j-1之间的任何字符相同,有则记录当前i到j的距离j-i和之前最长子串长度longest两者中的最大值到longest中,并i++直至字符串尾。

以上这种方法实现起来很轻松,但是考虑到i++和j++过程中各有一层循环,且遍历i到j之间也要一层循环,乘起来时间复杂度就是O(n^3)的级别了,自然是被时间卡住过不去的。于是我们要考虑在时间复杂度为O(n)的情况下通过。

我们可以这样想,最长不重复的子串只会被边界或重复的字符分界。很有可能最长的子串长度就出现在当前遍历到的字符与它上一次出现的位置的距离上。

我们用一个数组visit来分别存储字符串中可能出现的每个字符最后一次在已遍历的区域上出现的位置,即下标。visit初始全赋值为-1。鉴于本题的字符串中的字符均为英文字母,ASCII码值均不超过128,可以将visit长度定为128,直接哈希映射上即可。用变量longest记录在已遍历的区间上的最长子串长度。用变量last_start记录当前未重复子串的起始下标。

若当前遍历所到字符所对应的visit值为-1,说明字符串在这之前还没遇到相同字符,可以放心给当前不重复数+1并遍历下一个字符。
若当前遍历所到字符所对应的visit值不为-1,说明字符串在这之前已有相同字符,这时要比较当前字符上一次出现的位置是在最新起点last_start之前或之上还是之后。
在它之前的话仍可放心给当前不重复数+1并遍历下一个字符。
在它之上或者之后时,才要结束当前不重复子串的历史,并计算这个子串和之前的最长串哪个更长,最后再重新设定last_start到下一位置。

最后保留下来的longest值,就是我们所要求的最长子串长度了。

C++代码展示

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int visit[128];
        int dp = 0;//
        int last_start = 0, longest = 0;
        memset(visit, -1, sizeof(visit));

        for (int i = 0; i < s.size(); i++) {
            if (visit[s[i]] == -1 || last_start > visit[s[i]]) {
                dp++;
            } else {
                dp = i - visit[s[i]];
                last_start = visit[s[i]] + 1;
            }
            visit[s[i]] = i;
            longest = max(longest, dp);
        }
        return longest;
    }
};
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值