LeetCode演算法3:java 無重複字元的最長子串
阿新 • • 發佈:2018-12-23
問題描述
給定一個字串,請你找出其中不含有重複字元的 最長子串 的長度。
示例 1:
輸入: “abcabcbb”
輸出: 3
解釋: 因為無重複字元的最長子串是 “abc”,所以其長度為 3。
示例 2:
輸入: “bbbbb”
輸出: 1
解釋: 因為無重複字元的最長子串是 “b”,所以其長度為 1。
示例 3:
輸入: “pwwkew”
輸出: 3
解釋: 因為無重複字元的最長子串是 “wke”,所以其長度為 3。
請注意,你的答案必須是 子串 的長度,“pwke” 是一個子序列,不是子串。
解題思路
核心解決思路是用“視窗”向前推進,儲存當前最大的無重複字串長度。只需要從起始點推進右側邊界,在遇到重複值後,將視窗的左側邊界跟進,直到視窗內字元不再重複。之後再繼續推進右側視窗,直到又視窗達到字串最右側。即可儲存到最大值。
程式碼參考
對於字元的儲存有兩種方式,因為儲存內容的差異,導致了進行迴圈時的策略。
set儲存方式由於沒有記錄左側視窗的位置,使左側視窗通過迴圈跟進。map方式可以記錄左側視窗位置,可以使左側視窗跳躍式跟進。
set
public int lengthOfLongestSubstring(String s){ Set<Character> set = new HashSet<Character>(); int stringlen = s.length(); int len = 0; int i = 0; int j = 0; while(i < stringlen && j < stringlen){ if(!set.contains(s.charAt(j))){ set.add(s.charAt(j)); len = Math.max(len,j-i+1); j++; }else{ set.remove(s.charAt(i)); i++; } } return len; }
注:由於對於左側視窗跟進時迴圈次數未知,因此採用while迴圈
map
public int lengthOfLongestSubstring(String s){ HashMap<Character,Integer> map = new HashMap<>(); Set<Character> set = new HashSet<Character>(); int stringlen = s.length(); int len = 0; for(int j =0,i = 0; j < stringlen ; j++){ if(map.containsKey(s.charAt(j))){ i = Math.max(map.get(s.charAt(j)),i); } len = Math.max(len, j-i+1); map.put(s.charAt(j),j+1); } return len; }
注:仍舊是隻需要控制j即右側視窗的一次一步的便宜,左側視窗由於可以記錄位置自動一次跳躍性跟進,所以採用了for迴圈。
總體上map儲存比set儲存減少了迴圈次數。但增加了儲存空間。