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--无重复字符的最长子串

leetcode-003无重复字符的最长子串--python

leetcode-003无重复字符的最长子串--python

leetcode-003无重复字符的最长子串--python

LeetCode 003. 无重复字符的最长子串 双指针

LeetCode--003--无重复字符的最长子串(java)