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.

题目分析

方法一:复杂度为O( n2 ),以某个index的开始子串依次扩展长度,扩展到有重复字符的地方停止,记录下此时的子串长度,并把index右移一位重复上述过程,直到没得扩展为止。
方法二:双指针扫描,双指针i,j分别指向子串的开始位置和结束位置,如果结束位置的字符没有在该子串出现过j右移一位,否则i右移到最近出现重复字符的下一位(举个例子:"pwwbed" i=0,j=2时发现有重复的w,最近的w在1的位置,所以i移到1+1=2的位置,因为如果i只是右移一位的话w和w又重复了)并与目前最长字串长度比较取最大者,依次下去即可得到结果,复杂度O(n)。

代码与结果

方法一代码:

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int len = 0;
        for(int i = 0; i < s.length(); ++i)
        {
            string substr = "a";
            substr[0] = s[i];
            int sublen = 1;
            for(int j = i + 1; j < s.length(); ++j)
            {
                string str = "a";
                str[0] = s[j];
                if(substr.find(str) == string::npos)
                {
                    substr += str;
                    sublen++;
                }
                else 
                    break;
            }
            if(sublen>len)
                len = sublen;
        }
        return len;
    }
};

这是最初写的代码,中间还出了点小插曲,这里总结一下:不能用String s = "" + "a",这样写的话s的值并不是"a",而是一个指针因为""初始化的时候是一个地址(类似于一个数组),应该是这么解释>_<。这个代码应该比较好理解。

方法一结果

方法二代码

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int len = s.length();
        if(len < 2)
            return len;
        int start = 0, end = 1, ans = 1;
        map<char,int> M; M[s[0]] = 0;
        while(start < len && end < len)
        {
            if(M.count(s[end])>0 && M[s[end]] >= start && M[s[end]] < len && start != end)
            {
                ans = ans>(end-start)?ans:(end-start);
                start = M[s[end]] + 1;
                M[s[end]] = end;
                end++;
            }
            else
            {
                M[s[end]] = end;
                end++;
            }
        }
        return ans > (end-start)? ans:(end-start);
    }
};

这里面M用于存字母最近出现的位置,思路可以看上面。好像代码长度上没什么差别(果然我还是太菜了!),但是实际运行时间快了很多,看下面。

方法二结果

网上代码

方法跟第二种方法类似:

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        unordered_map<char,int> um;//um记录遍历过程中每个字符最后出现的位置
        int res=0,i=0,j=0; //j记录当前不重复子串的起点,i记录当前不重复子串的终点

        while(i<s.size()){ //遍历字符串
            if(um.find(s[i])!=um.end() && um[s[i]]>=j ) //如果当前维护的不重复子串中出现了s[i]
                j=um[s[i]]+1;   //更新j
            else  //如果当前维护的不重复子串中没有出现s[i]
                res=max(res,i-j+1); //更新结果,取较大者

            um[s[i]]=i; //更新um
            i++;
        }
        return res;
    }
};

哇,代码是不是很短,厉害了。但是我的运行时间比他的短哈哈。

网上代码结果


自我感觉这篇博客质量不是很好,大家看看就好,不喜勿喷。

发布了30 篇原创文章 · 获赞 1 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/lvmy3/article/details/72780285