Leetcode 003 Longest Substring Without Repeating Characters

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Gongzq5/article/details/81211219

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 ( n 3 )
具体分析:

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

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

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

猜你喜欢

转载自blog.csdn.net/Gongzq5/article/details/81211219