1. 程式人生 > >LeetCode演算法3:java 無重複字元的最長子串

LeetCode演算法3:java 無重複字元的最長子串

問題描述
給定一個字串,請你找出其中不含有重複字元的 最長子串 的長度。

示例 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儲存減少了迴圈次數。但增加了儲存空間。