码迷,mamicode.com
首页 > 其他好文 > 详细

LEETCODE 003 找出一个字符串中最长的无重复片段

时间:2017-09-12 12:03:18      阅读:145      评论:0      收藏:0      [点我收藏+]

标签:pen   images   while   str   com   bin   结构   limits   dex   

题目:

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 找出一个字符串中最长的无重复片段

标签:pen   images   while   str   com   bin   结构   limits   dex   

原文地址:http://www.cnblogs.com/qins/p/7509059.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!