Given a string, find the length of the longest substring without repeating characters.java
給定一個字符串,請你找出其中不含有重複字符的 最長子串 的長度。指針
示例 1:code
輸入: "abcabcbb" 輸出: 3 解釋: 由於無重複字符的最長子串是 "abc",因此其長度爲 3。
示例 2:blog
輸入: "bbbbb" 輸出: 1 解釋: 由於無重複字符的最長子串是 "b",因此其長度爲 1。
示例 3:索引
輸入: "pwwkew" 輸出: 3 解釋: 由於無重複字符的最長子串是 "wke",因此其長度爲 3。 請注意,你的答案必須是 **子串** 的長度,"pwke" 是一個子序列,不是子串。
<!--more-->ip
remove
掉 -- 後面發現只remove掉那個重複的字符的話,有些沒有重複的字符在回退以後再次計算的時候,會發生混亂<font color=grey size=2>(回退後再次走到以前不重複的字符時候,由於hash
表中已經在第一次put
過了,因此此次必定會發生重複狀況)</font>上面方法應該是 $ O(n^2) $ ,由於會發生例如
abcdea
在最後a
發生重複,就會徹底回退到b
位置---so low ;提交記錄耗時大概80+ms內存
map<Character,Integer>
中存放的以前被重複字符的value(即字符所在的索引)換爲當前發生重複的字符位置 -- 不是被重複字符max
最大j,k
表明的都是索引,因此最後結果 爲max+1
Two和Three 提交的耗時6ms,佔用內存35M--佔用內存居然超過了 100%的java用戶ヽ(°◇° )ノ資源
package com.dasnnj.practice.medium; import java.util.HashMap; import java.util.Map; /** * Description <p> TODO: * 給定一個字符串,請你找出其中不含有重複字符的 最長子串 的長度。 * <p> * 示例 1: * <p> * 輸入: "abcabcbb" * 輸出: 3 * 解釋: 由於無重複字符的最長子串是 "abc",因此其長度爲 3。 * 示例 2: * <p> * 輸入: "bbbbb" * 輸出: 1 * 解釋: 由於無重複字符的最長子串是 "b",因此其長度爲 1。 * 示例 3: * <p> * 輸入: "pwwkew" * 輸出: 3 * 解釋: 由於無重複字符的最長子串是 "wke",因此其長度爲 3。 * 請注意,你的答案必須是 子串 的長度,"pwke" 是一個子序列,不是子串。</p> * * @author DASNNJ <a href="mailto:dasnnj@outlook.com.com"> dasnnj@outlook.com </a> * @date 2019-05-08 13:17 */ public class LongestSubstringWithoutRepeatingCharacters { public static void main(String[] args) { LongestSubstringWithoutRepeatingCharacters l = new LongestSubstringWithoutRepeatingCharacters(); System.out.println(l.lengthOfLongestSubstring("")); } public int lengthOfLongestSubstring(String s) { //One /*char[] chars = s.toCharArray(); Map<Character, Integer> map = new HashMap<>(8); //計算非重複字符的長度 Integer len = 0; int max = 0; //索引 Integer index; for (int i = 0; i < chars.length; i++) { //若是是正常進行 //若是重複 if ((index = map.get(chars[i])) != null) { //回退到重複的位置,從重複位置的下一位從新算,至關於捨棄兩個重複字符中的第一個 i = index; //長度歸零 len = 0; //將map清空,從重複位置的下一位置從新計算 -- 清空是由於第一個重複的在上面提到是至關於捨棄,不清空的話會影響下次循環的判斷 map.clear(); } else { //沒重複固然正常put 正常++ map.put(chars[i], i); len++; } //每次循環都保持max最大 if (len > max) { max = len; } } return max;*/ if ("".equals(s)) { return 0; } char[] chars = s.toCharArray(); //j k,用於Two方法的兩個指針---後面發現直接用for循環便可 int j = 0, k = 0, max = 0; Integer ele; Map<Character, Integer> sets = new HashMap<>(16); //Three for (int m = 0; m < chars.length; m++) { //若是發生重複 if ((ele = sets.get(chars[m])) != null) { // j指針指向兩個重複字符中的第一個的下一位置,j指針不能後退,只能前進,因此下面有個判斷 if (j < ele + 1) { j = ele + 1; } } //不重複則是正常put,重複狀況1.將j指針指向原字符的下一位2.用新字符替換掉map中原字符(主要是爲了替換map中key爲此字符 的value值也就是索引) sets.put(chars[m], m); //每次循環保持max最大 if (max < m - j) { max = m - j; } } //Two 原理同Three /*while (j < chars.length && k < chars.length) { if ((ele = sets.get(chars[k])) != null) { if (j < ele + 1) { j = ele + 1; } } sets.put(chars[k], k); k++; if (max < k - j) { max = k - j; } }*/ return max + 1; } }