Leetcode 003 Longest Substring Without Repeating Characters

Leetcode 003 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.


最终的Solution

int lengthOfLongestSubstring(string s) {
    int mostRecentlyPosition[256], start = -1, maxLen = 0;
    for (int i=0; i<256; i++) {
        mostRecentlyPosition[i] = -1;
    }
    for (int i=0; i<s.length(); i++) {
        if (mostRecentlyPosition[s[i]] > start) {
            start = mostRecentlyPosition[s[i]];
        }
        mostRecentlyPosition[s[i]] = i;
        maxLen = max(maxLen, i - start);
    }
    return maxLen;
}

分析

这个解法是比较好的,明显可以看到,只有一重循环,次数是s的长度,时间复杂度达到了O(n)

这个解法的思想大致是这样的,mostRecentlyPosition记录每个字符出现的最后位置,start记录我们当前计算的子字符串的开始位置。

我们以"pwwkew"为例:

  • 我们将mostRecentlyPosition都置为-1,start也置为-1
  • 首先,遍历p,w,可以记录mostRecentlyPosition['p'] = 0, mostRecentlyPosition['w'] = 1
  • 下面又到了w,此时我们发现mostRecentlyPosition['w'] = 1 > start,这代表着w字符在我们当前计算的子字符串中已经出现过了。因此我们将第一次出现的w从我们的字符串中删去,也就是start变成w第一次出现位置的后一位,这样我们的子字符串中就没有重复的元素了。当然,此时我们要记录在遇到这个重复的w之前一个时刻,我们计算到的字符串的最大长度;
  • 重复上述步骤

实际的使用中,由于我们初始start = -1,我们不将start标号的字符算在字符串中,因此我们没有+1。


之前还写过一些简单的方案

初始Solution

bool repeat[256];
string s;
int lengthOfLongestSubstring(string str) 
{
    s = str;
    int len = s.length();
    // O(n)
    while (len != 0) 
    {
        // O(n)
        for (int i = 0; i + len <= s.length(); i++) 
        {
            // O(n)
            if (!hasRepeat(i, i + len))
            {
                return len;
            }
        }
        len--;
    }
    return 0;
}
// O(n)
bool hasRepeat(int start, int end) 
{
    for (int i = 0; i < 256; i++) repeat[i] = false;
    for (int i = start; i < end; ++i) {
        if (repeat[s[i]]) return true;
        repeat[s[i]] = true;
    }
    return false;
}

分析

这里就是巧妙地的暴力破解了,采用了一个浮动窗口,窗口的长度lenstring s的长度,递减到0。每次都验证s中连续的len个字符是否重复,若重复则不符合;若不重复,那么就是最长的子串,直接return len

简单的分析该方法的时间复杂度,三重循环大致为 O(n3) O ( n 3 )
具体分析:

  • 最外层while(len != 0) {...} O(n) O ( n )
  • 次外层for (int i = 0; i + len <= s.length(); i++) {...} O(nlen) O ( n − l e n )
  • 内层hasRepeat(i, i + len) O(len) O ( l e n )

总体的复杂度为 O[n(nlen)len]=O(n34) O [ n ( n − l e n ) l e n ] = O ( n 3 4 )

嘿嘿其实我也不确定这个具体分析对不对,反正粗略来说肯定是 O(n3) O ( n 3 ) 是没错了

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值