1. 程式人生 > >【leetcode演算法-無重複字元的最長子串】

【leetcode演算法-無重複字元的最長子串】

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

示例 1:

輸入: "abcabcbb"
輸出: 3 
解釋: 因為無重複字元的最長子串是 "abc",所以其長度為 3。


示例 2:

輸入: "bbbbb"
輸出: 1
解釋: 因為無重複字元的最長子串是 "b",所以其長度為 1。

1、暴力破解

package leetcode;

import java.util.HashSet;

public class Demo2 {

	public static int LengthOfLongestSubstring(String str)
    {
        int resLength = 0;
        int strLength = str.length();
        HashSet<String> hashSet = new HashSet<String>();
        for (int i = 0; i < strLength; i++)
        {
            for (int j = i + 1; j < strLength; j++)
            {
                //這裡能確定str的所有子串

            	String strChildren = str.substring(j, j+1);
                if (hashSet.contains(strChildren))
                {
                    break;
                }
                else
                {
                    hashSet.add(strChildren);
                }
               
            }
        }
        return resLength; 
    }
	public static void main(String[] args) {
		
		System.out.println(Demo2.LengthOfLongestSubstring("ababedf"));
	}

}

2、大佬解法

    滑動視窗,通過使用 HashSet 作為滑動視窗,我們可以用 O(1) 的時間來完成對字元是否在當前的子字串中的檢查。滑動視窗是陣列/字串問題中常用的 抽象概念。 視窗通常是在陣列/字串中由開始和結束索引定義的一系列元素的集合,即 [i, j)(左閉,右開)。而滑動視窗是可以將兩個邊界向某一方向“滑動”的視窗。例如,我們將 [i, j)向右滑動 1 個元素,則它將變為 [i+1, j+1)(左閉,右開)。

     回到我們的問題,我們使用 HashSet 將字元儲存在當前視窗 [i, j)(最初 j = i)中。 然後我們向右側滑動索引 j,如果它不在 HashSet 中,我們會繼續滑動 j。直到 s[j] 已經存在於 HashSet 中。此時,我們找到的沒有重複字元的最長子字串將會以索引 i開頭。如果我們對所有的 i 這樣做,就可以得到答案。

     2.1、程式碼實現

public static int LengthOfLongestSubstring3(String str)
	 {
	     int resLength = 0;
	     int strLength = str.length();
	     int i = 0, j = 0;
	     HashSet<String> hashSet = new HashSet<String>();
	 
	     while (i < strLength && j < strLength)
	     {
	    	 String oneStrJ = str.substring(j,j+1);
	         if (!hashSet.contains(oneStrJ))
	         {
	             hashSet.add(oneStrJ);
	             j++;
	             resLength = Math.max(resLength,j-i);
	         }
	         else
	         {
	        	 String oneStrI = str.substring(i, i+1);
	             hashSet.remove(oneStrI);
	             i++;
	         }
	     }
	     return resLength;
	 }

      2.2 程式碼實現:

     (1)快指標j所在元素不重複,更新max,將快指標j元素在hash表中的標記為出現,後移j ;
     (2)快指標j所在元素重複,慢指標後移,此時將慢指標i元素在hash表中的標記清除。此時並不關心是誰重複,重複元素前的元素都要清除掉。

	public static int lengthOfLongestSubstring(String s) {
        int []hash = new int [500];
        int max = 0;
        int i = 0, j = 0;

        while (i < s.length() && j <s.length() ) {
            if(hash[s.charAt(j)] == 0) {
                hash[s.charAt(j)] = 1;
                j++;
                max = (j - i) > max ? (j - i) : max;
            } else {
                hash[s.charAt(i)] = 0;
                i++;
            }  
        }
        return max; 
    }