leetcode 3. Longest Substring Without Repeating Characters (无重复字符的最长子串)双指针法

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

Example 1:

Input: “abcabcbb”
Output: 3
Explanation: The answer is “abc”, with the length of 3.
Example 2:

Input: “bbbbb”
Output: 1
Explanation: The answer is “b”, with the length of 1.
Example 3:

Input: “pwwkew”
Output: 3
Explanation: 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)O(n^2)),然后判断每个子串是否符合要求(O(n)O(n)),总的复杂度是 O(n3)O(n^3)

进一步,可以用一个 map 来存每个字母上一次的出现位置,当枚举的尾指针右移时,更新一下新字母的次数,假如该字母已经出现过,并且该位置在当前头尾指针的区间内,则直接移动头指针至当前尾指针处字符前一次的出现位置之后,总的时间复杂度是 O(n)O(n)

总结一下就是双指针法。

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int len=s.length();
        unordered_map<char,int> m;
        int i=0,j=0,res=0;
        while(j<len){
            if(m.find(s[j])!=m.end())
                i=max(i,m[s[j]]+1);
            m[s[j]]=j;
            res=max(res,j-i+1);
            j++;
        }
        return res;
    }
};

暴力枚举 O(n3)O(n^3)

  • 暴力枚举的几个代码都是 TLE 的,写着玩玩

Java

class Solution {
    public int lengthOfLongestSubstring(String s) {
        int n=s.length();
        int res=0;
        for(int i=0;i<n;i++)
            for(int j=i+1;j<=n;j++)
                if(check(s,i,j))res=Math.max(res,j-i);
        return res;
    }
    public boolean check(String s, int begin, int end){
        Set<Character> set=new HashSet<>();
        for(int i=begin;i<end;i++){
            Character ch=s.charAt(i);
            if(set.contains(ch))return false;
            set.add(ch);
        }
        return true;
    }
}
  • 会 TLE

C++

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int n=s.length();
        int res=0;
        for(int i=0;i<n;i++)
            for(int j=i+1;j<=n;j++)
                if(check(s,i,j))res=max(res,j-i);
        return res;
    }
    bool check(string s,int begin,int end){
        set<int> a;
        for(int i=begin;i<end;i++){
            char c=s[i];
            if(a.find(c)!=a.end())return false;
            a.insert(c);
        }
        return true;
    }
};

Python

class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        res = 0
        n = len(s)
        for i in range(n):
            for j in range(i+1,n+1):
                if self.check(s,i,j):
                    res = max(res, j-i)
        return res
    
    def check(self, s, begin, end):
        m = []
        for i in range(begin, end):
            if s[i] in m:
                return False
            m.append(s[i])
        return True

Go

func lengthOfLongestSubstring(s string) int {
    n:=len(s)
    res:=0
    for i:=0;i<n;i++{
        for j:=i+1;j<=n;j++{
            if check(s,i,j){
                if j-i>res{
                    res=j-i
                }
            }
        }
    }
    return res
}
func check(s string, b, e int) bool {
    m:=make(map[byte]bool)
    for i:=b;i<e;i++{
        if m[s[i]]==true{
            return false
        }
        m[s[i]]=true
    }
    return true
}

双指针法 O(n)O(n)

Java

class Solution {
    public int lengthOfLongestSubstring(String s) {
        int n=s.length();
        int res=0;
        Map<Character, Integer> mp=new HashMap<>();
        for(int j=0,i=0;j<n;j++){
            if(mp.containsKey(s.charAt(j)))
                i=Math.max(mp.get(s.charAt(j))+1,i);
            res=Math.max(res,j-i+1);
            mp.put(s.charAt(j),j);
        }
        return res;
    }
}
  • 字符的取值范围确定的话可以这样写:
class Solution {
    public int lengthOfLongestSubstring(String s) {
        int n=s.length();
        int res=0;
        int[] mp=new int[256];
        for(int j=0,i=0;j<n;j++){
            i=Math.max(mp[s.charAt(j)],i);
            res=Math.max(res,j-i+1);
            mp[s.charAt(j)]=j+1;
        }
        return res;
    }
}

C++

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int n=s.length();
        int res=0;
        unordered_map<char,int> mp;
        for(int i=0,j=0;j<n;j++){
            if(mp.find(s[j])!=mp.end())
                i=max(mp[s[j]]+1,i);
            mp[s[j]]=j;
            res=max(res,j-i+1);
        }
        return res;
    }
};
  • 数组 map
class Solution {
public:
    int mp[256];
    int lengthOfLongestSubstring(string s) {
        int n=s.length();
        int res=0;
        for(int i=0,j=0;j<n;j++){
            i=max(i,mp[s[j]]);
            mp[s[j]]=j+1;
            res=max(res,j-i+1);
        }
        return res;
    }
};

Python

class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        res = 0
        j = 0
        m = {}
        for i, c in enumerate(s):
            if c in m:
                j = max(j, m[c]+1)
            m[c] = i # store where c last appears
            res = max(res, i-j+1)
        return res

Go

func lengthOfLongestSubstring(s string) int {
    m:=make(map[rune]int)
    res:=0
    left:=0
    for i,c:=range s{
        if _,ok:=m[c]; ok==true&&m[c]>=left{
            left=m[c]+1
        }
        res=max(res,i-left+1)
        m[c]=i
    }
    return res
}
func max(a,b int)int{
    if a>b{
        return a
    }
    return b
}
posted @ 2020-05-04 12:53  winechord  阅读(89)  评论(0编辑  收藏  举报