面試題:求給定字符串中最長無重復子字符串的長度。


題干:

Given a string, find the length of the longest substring without repeating characters.

Examples:

Given "abcabcbb", the answer is "abc", which the length is 3.

Given "bbbbb", the answer is "b", with the length of 1.

Given "pwwkew", 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.


 

解法一:

列出所有字符串,並判斷是否有重復字符。(最直觀的方法,但是運算量極大,不要用)

public class Solution {
    public int lengthOfLongestSubstring(String s) {
        int n = s.length();
        int ans = 0;
        for (int i = 0; i < n; i++)
            for (int j = i + 1; j <= n; j++)
                if (allUnique(s, i, j)) ans = Math.max(ans, j - i);
        return ans;
    }

    public boolean allUnique(String s, int start, int end) {
        Set<Character> set = new HashSet<>();
        for (int i = start; i < end; i++) {
            Character ch = s.charAt(i);
            if (set.contains(ch)) return false;
            set.add(ch);
        }
        return true;
    }
}

解法二:

利用HashSet做划窗來判斷字符唯一性。(用這個)

public class LengthOfLongestSubstring3 {
	/*
	 * 思路:
	 * 	用Set做一個范圍為 [i,j)的划窗(利用Set檢查char的唯一性)。
	 * 	在確定s[i,j-1]沒有重復字符的情況下,只需檢查s[j]是否存在於s[i,j-1]中就可以了。
	 * 	如果s[j]存在於s[i,j-1]中,那么划窗變為 [i+1,j),繼續檢查。
	 * 
	 **/
	public int lengthOfLongestSubstring(String s) {
		int n = s.length();
		Set<Character> set = new HashSet<>();
		int ans = 0, i = 0, j = 0;
		while (i < n && j < n) {
			// try to extend the range [i, j]
			if (!set.contains(s.charAt(j))) {
				// 此處是根據角標j來遍歷,一個一個的往里存
				set.add(s.charAt(j++));
				ans = Math.max(ans, j - i);//注意這里為什么是j-1而不是j-i+1呢?因為j已經++了
			} else {
				set.remove(s.charAt(i++));
			}
		}
		return ans;
	}
}

思考:整個流程中,角標是如何變化的?以及while(i<n & j<n)配合i++和j++這種代碼結構。


解法三:

利用HashMap建立{字符-索引}的映射,降低找重復時的時間復雜度(優解但是不太好想)

public class Solution {
	/*
	 * 思路: 使用HashMap存放{字符-索引}的映射,當我們發現重復的字符時,直接跳過這些字符。
	 * 通過遍歷j來循環。如果遍歷到j時,s[i,j)中有重復元素s[j],我們不再一點一點移動i的位置了,
	 * 若重復元素角標為j',直接跳過[i,j′]這個區間即可,直接將i賦值為j'+1。
	 * 
	 */
	public int lengthOfLongestSubstring(String s) {
		int n = s.length(), ans = 0;
		// Hashmap中存放的是 字符-索引
		Map<Character, Integer> map = new HashMap<>();
		// try to extend the range [i, j]
		for (int j = 0, i = 0; j < n; j++) {
			if (map.containsKey(s.charAt(j))) {
				// 如果map里已經有這個index[j]處的char,將i賦成j+1。
				i = Math.max(map.get(s.charAt(j)) + 1, i);
			}
			// 注意這里的max,適用於“abba”這種情況,“a”雖然存在於map中了,但i也不移動
			ans = Math.max(ans, j - i + 1);
			// 將char加入哈希表中,value為索引值j。
			map.put(s.charAt(j), j);
		}
		return ans;
	}
}

  思考:怎么用一次循環完成整個算法的?想清楚整個流程中兩個索引i,j是怎么變化的。

      *注意max*


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM