LeetCode筆記3——無重複字元的最長子串
題目:
給定一個字串,找出不含有重複字元的最長子串的長度。
示例 1:
輸入: "abcabcbb"
輸出: 3
解釋: 無重複字元的最長子串是 "abc",其
長度為 3。
示例 2:
輸入: "bbbbb"
輸出: 1
解釋: 無重複字元的最長子串是 "b"
,其長度為 1。
示例 3:
輸入: "pwwkew" 輸出: 3 解釋: 無重複字元的最長子串是"wke"
,其長度為 3。 請注意,答案必須是一個子串,"pwke"
是一個子序列 而不是子串。
思路1 暴力法:依次檢查字串中 的每一個字元,將其加入到Hashset中。如果不包含該字元就新增,並記錄set的大小;如果包含的話,就將set情空。
程式碼:
class Solution { public int lengthOfLongestSubstring(String s) { int N=s.length(); if(N==1) return 1; Set <Character>hashset=new HashSet<>(); //HashSet的建立 int j=0; int max=0; while(j<N) { int i=j+1; hashset.add(s.charAt(j)); while(i<N) { Character tem=s.charAt(i); if(!hashset.contains(tem)) { hashset.add(tem); i++; max=Math.max(max,hashset.size()); } else { max=Math.max(max,hashset.size()); hashset.clear(); //i++; break; //這裡遇見相等的直接跳出內迴圈,i再加1 的話會出錯 } } j++; } return max; } }
思路2:(以下均摘自leetcode解答)
優化的滑動視窗
上述的方法最多需要執行 2n 個步驟。事實上,它可以被進一步優化為僅需要 n 個步驟。我們可以定義字元到索引的對映,而不是使用集合來判斷一個字元是否存在。 當我們找到重複的字元時,我們可以立即跳過該視窗。
也就是說,如果 s[j]s[j]s[j] 在 [i,j)[i, j)[i,j) 範圍內有與 j′j'j′ 重複的字元,我們不需要逐漸增加 iii 。 我們可以直接跳過 [i,j′]
範圍內的所有元素,並將 iii 變為 j′+1j' + 1j′+1。
public class Solution { public int lengthOfLongestSubstring(String s) { int n = s.length(), ans = 0; Map<Character, Integer> map = new HashMap<>(); // current index of character // try to extend the range [i, j] for (int j = 0, i = 0; j < n; j++) { if (map.containsKey(s.charAt(j))) { i = Math.max(map.get(s.charAt(j)), i); } ans = Math.max(ans, j - i + 1); map.put(s.charAt(j), j + 1); } return ans; } }
思路3:
以前的我們都沒有對字串 s
所使用的字符集進行假設。
當我們知道該字符集比較小的時侯,我們可以用一個整數陣列作為直接訪問表來替換 Map
。
常用的表如下所示:
int [26]
用於字母 ‘a’ - ‘z’或 ‘A’ - ‘Z’int [128]
用於ASCII碼int [256]
用於擴充套件ASCII碼
public class Solution { public int lengthOfLongestSubstring(String s) { int n = s.length(), ans = 0; int[] index = new int[128]; // current index of character // try to extend the range [i, j] for (int j = 0, i = 0; j < n; j++) { i = Math.max(index[s.charAt(j)], i); ans = Math.max(ans, j - i + 1); index[s.charAt(j)] = j + 1; } return ans; } }