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.


第一种方法使用哈希表(map实现),key是字符值,value是字符在字符串中的索引,对字符串s进行扫描,如果当前位置的字符没有在前面的扫描过程中出现过,则把该字符放入集合中,如果当前位置的字符曾经在前面扫描过程中出现过

(如果出现多次我们只保存最近出现的那个),则把上一个出现的字符删除,再把当前字符放入集合中,判断字符是否出现过使用哈希表。扫描过程中出现的最大集合的元素个数为答案。

 1 class Solution {
 2     public int lengthOfLongestSubstring(String s) {
 3         if (s.length() == 0) return 0;
 4         char []s1 = s.toCharArray();
 5         int ans = 1;
 6         Map<String, Integer> map = new HashMap<>();
 7         int num = 0;
 8         for (int i = 0; i < s.length(); ++i) {
 9             String tc = String.valueOf(s1[i]);
10             if (map.containsKey(tc)) {
11                 int temp = i - map.get(tc);
12                 if (temp <= num) {
13                     num = temp;
14                 } else {
15                     num++;
16                 }
17                 
18             } else {
19                 num++;
20             }
21             map.put(tc, i); 
22                 
23             
24             if (num > ans) {
25                 ans = num;
26             }
27         }
28         return ans;
29     }
30 }

 

第二种办法是用set来判断字符是否出现重复,其他与第一种相同

 1 class Solution {
 2     public int lengthOfLongestSubstring(String s) {
 3         Set<Character> set = new HashSet<>();
 4         int i = 0, j = 0;
 5         int n= s.length();
 6         int ans = 0;
 7         while (i < n && j < n) {
 8             if (set.contains(s.charAt(j))) {
 9                 
10                 set.remove(s.charAt(i++));
11             } else {
12                 set.add(s.charAt(j++));
13                 ans = Math.max(ans, j - i);
14             }
15         }
16         
17         
18         return ans;
19     }
20 }
View Code

第三种方法,设f[i] = j为开始索引为i的最大无重复字符子串的结束索引为j,我们的目标是求出f[i] (i €[0, n - 1], n为字符串的长), 对字符串进行扫描,若当前位置字符没有在前面的扫描过程出现过

i的值不变,j的值往后走一位,如果当前位置字符曾经在前面的扫描过程出现过(如果出现多次我们只保存最近出现的那个),设最近出现的那个索引为k, 更新i = max(i + 1, k + 1),扫描过程中出现的最大集合为所求。

 1 class Solution {
 2     public int lengthOfLongestSubstring(String s) {
 3         Map<Character, Integer> map = new HashMap<>();
 4         int ans = 0;
 5         int n = s.length();
 6         for (int i = 0, j = 0; j < n; ++j) {
 7             if (map.containsKey(s.charAt(j))) {
 8                 i = Math.max(i, map.get(s.charAt(j)) + 1);
 9                 
10             } 
11             ans = Math.max(j - i + 1, ans);
12             map.put(s.charAt(j), j);
13         }
14         
15         
16         return ans;
17     }
18 }
View Code

 第四种方法用一维数组实现哈希表,长度为128,因为ascii码的长度为7bit, 2 ^ 7 = 128

 1 class Solution {
 2     public int lengthOfLongestSubstring(String s) {
 3         int []map = new int[128];
 4         int ans = 0;
 5         int n = s.length();
 6         for (int i = 1, j = 0; j < n; ++j) {
 7             
 8             i = Math.max(i, map[s.charAt(j)] + 1);
 9                 
10         
11             ans = Math.max(j + 1 - i + 1, ans);
12             map[s.charAt(j)] = j + 1;
13         }
14         
15         
16         return ans;
17     }
18 }
View Code

 

posted @ 2020-01-17 14:56  hyx1  阅读(112)  评论(0编辑  收藏  举报