LEETCODE 003 找出一个字符串中最长的无重复片段
Posted MrQin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LEETCODE 003 找出一个字符串中最长的无重复片段相关的知识,希望对你有一定的参考价值。
题目:
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.
解答:
方法一:
最笨的方法,截取字符串的片段,检测片段有没有重复。建立i,j两个index,i从0~n-1, j从i+1到n, 然后截取i ,j 之间的字符串,检测是不是重复的字符串。
代码
1 public class Solution { 2 public int lengthOfLongestSubstring(String s) { 3 int n = s.length(); 4 int ans = 0; 5 for (int i = 0; i < n; i++) 6 for (int j = i + 1; j <= n; j++) 7 if (allUnique(s, i, j)) ans = Math.max(ans, j - i); 8 return ans; 9 } 10 11 public boolean allUnique(String s, int start, int end) { 12 Set<Character> set = new HashSet<>(); 13 for (int i = start; i < end; i++) { 14 Character ch = s.charAt(i); 15 if (set.contains(ch)) return false; 16 set.add(ch); 17 } 18 return true; 19 } 20 }
时间复杂度:
allUnique 方法中 要查看字符串[i,j)有没有重复,我们需要全部遍历一遍, 时间复杂度未O(j-i)。
对于 指定的一个i值, 从i+1到n的j 耗时的总和是
所以,总时间为
空间复杂度,
我们需要O(k)的空间来检测一个字符串是否重复, k的值为Set的大小。而k的值最大不会超过String的长度n和字符集或字母表的长度m。
注:Set的数据结构是Hash表,这里的字符集和字母表长度指的是hash表的散列长度。
方法二:
我们可以看到,方法一里面有重复检测的,当一个字符串s[i,j-1)已知是非重复(前面检测过)的,那么我们检测s[i,j)只需要检测s[j]在不在s[i,j-1)里面即可。
我们可以利用HashSet来保存字符串片段,检测一个字符是否存在HashSet中时间复杂度为O(1)。
定义两个index分别是i 和 j, i,j之间为字符串,HashSet存i,j之间的字符。
当s[j]不包含在[i,j)之间,j先移动,扩大i,j之间字符串长度,直到s[j]包含在[i,j)之间;
当s[j]包含在[i,j)之间, i移动, 缩小i,j之间字符串长度,直到直到s[j]不包含在[i,j)之间。
代码:
1 public class Solution { 2 public int lengthOfLongestSubstring(String s) { 3 int n = s.length(); 4 Set<Character> set = new HashSet<>(); 5 int ans = 0, i = 0, j = 0; 6 while (i < n && j < n) { 7 // try to extend the range [i, j] 8 if (!set.contains(s.charAt(j))){ 9 set.add(s.charAt(j++)); 10 ans = Math.max(ans, j - i); 11 } 12 else { 13 set.remove(s.charAt(i++)); 14 } 15 } 16 return ans; 17 } 18 }
时间复杂度:
最坏情况,每个i,j之间的元素都被访问一遍,o(2n)=o(n)。
空间复杂度,同上,o(max(m,n))
方法三:
上面的方法最坏情况时间需要2n, 而最好的情况也需要n。我们可以用一个Map<char,index> 来代替上面用来检查字符是否存在字符串中的Set,这样当我们找到重复的字符时候,我们就可以直接跳过重复字符前面的所有字符。
因为我们通过Map能知道重复字符的位置,我们就不需要将i一次一次地增加,然后一次一次去检测,而是直接全部跳过。
代码:
1 public class Solution { 2 public int lengthOfLongestSubstring(String s) { 3 int n = s.length(), ans = 0; 4 Map<Character, Integer> map = new HashMap<>(); // current index of character 5 // try to extend the range [i, j] 6 for (int j = 0, i = 0; j < n; j++) { 7 if (map.containsKey(s.charAt(j))) { 8 i = Math.max(map.get(s.charAt(j)), i); 9 } 10 ans = Math.max(ans, j - i + 1); 11 map.put(s.charAt(j), j + 1); 12 } 13 return ans; 14 } 15 }
思考:上面的map可以用数组来代替。
以上是关于LEETCODE 003 找出一个字符串中最长的无重复片段的主要内容,如果未能解决你的问题,请参考以下文章
leetcode-003无重复字符的最长子串--python
leetcode-003无重复字符的最长子串--python