LetCode-面試經典算法(java實現)【LetCode003: Longest Substring Without Repeating Characters】

一、題目描述

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

給定一個字符串,找出不含有重複字符的最長子串的長度。

          Example 1:
          Input: "abcabcbb"
          Output: 3 
          Explanation: The answer is "abc", with the length of 3. 
          Example 2:
          Input: "bbbbb"
          Output: 1
          Explanation: The answer is "b", with the length of 1.
          Example 3:
          Input: "pwwkew"
          Output: 3
          Explanation: 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.

二、解題思路

一眼看出,皆是暴力。用暴力法,可以很簡單的解決,但是時間複雜度就比較高一點。我是選擇用Java中的HashMap,進行二重循環,對第一層循環,每進行一次i++,就新建一個HashMap內存空間,爲了防止第i個字符所用的map中的值對第i+1個字符的map造成影響。再第二層循環中,進行的操作是判斷HashMap中是否有這個字符,如果有就跳出第二層循環,沒有的話就將該字符添加到Map中,然後將map的大小和最長字符的個數進行比較,大則賦值。

第二種方法,時間複雜度爲O(2n),定義二個int變量,一個用來控制字符串的字符位置,一個用來代表存放在HashSet中的字符位置,如果HashSet中沒有這個字符,就加入進去,如果有,就刪除HashSet下標i所指向的字符,並i++.獲取最大的長度:設置一個初值maxnum = 0,只要HashSet的值比maxnum大就將其賦予maxnum,最後返回maxnum的值。

第三種方法,改進的滑動窗口算法。用HashMap方法,將字符和下標聯繫起來,設置二個變量,i和j.j用來標識當前字符的下標。i用來標識重複字符的下標的下一個字符的下標。用j-i+1用來獲取未重複字符串的長度。如果hashmap中有某個字符,然後就獲取再hashmap中這個字符的下標和i作比較,選取較大的一個。(因爲可能會出現abba的出現,到最後一個字符的時候,於a重複的字符下標是0,而且i已經有值爲2.如果不選擇較大的一個值,就會出現錯誤的結果4,反之出現的結果是2.將該字符加入到hashmap中。直到將字符遍歷完。

第四種方法,用數組存放。因爲字符代表着0-256對於所有的ASCII碼。用下標代表字符,該下標存放的值是該字符在字符串中的位置,假設有重複的字符,那麼存放的值就變成最新重複的字符的下標。只要獲取到最新重複字符的下標和此時遍歷字符串的所處位置,就可計算出未重複字符的長度,獲取到最大值即可。

三、代碼實現

package com.acm.Secondmonth;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public class LetCode003 {
	/**
	 * 返回:最長沒有重複字符的個數
	 * 先用暴力法 
	 * 直接二重循環 對第一層循環的每一個值度找一下不重複字符串個數
	 * @param s
	 * @return
	 */
	public static int lengthOfLongestSubstring(String s) {
			if(s == null) {
				throw new RuntimeException("invaild input:S is null");
			}
			int max = 0;
			for(int i=0 ; i<s.length() && s.length()-i>=max ; i++) {
				Map<Character , Integer> result = new HashMap<>();
				for(int j=i ; j<s.length() ; j++) {
					if(result.containsKey(s.charAt(j))) {
						break;
					}else {
						result.put(s.charAt(j), j);
					}
					if(result.size() > max) {
						max = result.size();
					}
			
				}
			}
			
			return max;
	}
	
	/**
	 * 
	 * @param s
	 * @return
	 * 時間複雜度 O(2n)
	 * 每發現一個重複的字符就將一開始的字符刪除 ,一直到將與其重複的字符和其前面的全部刪除
	 */
	public static int lengthOfLongestSubstring01(String s) {
		if(s == null) {
			throw new RuntimeException("invaild input:S is null");
		}
		
		Set<Character> result = new HashSet<>();
		int i=0 , j=0 , maxNum = 0;
		while(i < s.length() && j < s.length()) {
			if(!result.contains(s.charAt(j))) {
				result.add(s.charAt(j++));
				if(result.size() > maxNum) {
					maxNum = result.size();
				}
			}else {
				result.remove(s.charAt(i++));
			}
			
		}
		return maxNum;
		
	}
	
	public static int lengthOfLongestSubstring03(String s ) {
		if(s == null) {
			throw new RuntimeException("invaild input:S is null");
		}
		
		int maxNum = 0;
		
		Map<Character, Integer> result = new HashMap<>();
		int start = 0 ; int end = 0;
		while(end < s.length()) {
			if(result.containsKey(s.charAt(end))) {
				start = Math.max(result.get(s.charAt(end))+1 , start);
			}
			result.put(s.charAt(end), end);
			
			maxNum = Math.max(maxNum, end-start+1);
			end++;
		}
		return maxNum;
	}
	
	public static int lengthOfLongestSubstring04(String s) {
		if(s == null) {
			throw new RuntimeException("invaild input:S is null");
		}
		int maxNum = 0;
		int[] result =new int[256];
		for(int i=0 , j=0 ; j<s.length() ; j++) {
			i = Math.max(result[s.charAt(j)], i);
			maxNum = Math.max(maxNum , j-i+1);
			result[s.charAt(j)] = j+1;
		}
		return maxNum;
	}
	public static void main(String[] args) {
		test01();
		test02();
		test03();
		test04();
	}
	
	private static void test01() {
		String test = "abcabcbb";
		System.out.println(lengthOfLongestSubstring(test));
		System.out.println(lengthOfLongestSubstring01(test));
		System.out.println(lengthOfLongestSubstring03(test));
		System.out.println(lengthOfLongestSubstring04(test));
	}
	private static void test02() {
		String test = "abba";
		System.out.println(lengthOfLongestSubstring(test));
		System.out.println(lengthOfLongestSubstring01(test));
		System.out.println(lengthOfLongestSubstring03(test));
		System.out.println(lengthOfLongestSubstring04(test));
	}
	private static void test03() {
		String test = "pwwkew";
		System.out.println(lengthOfLongestSubstring(test));
		System.out.println(lengthOfLongestSubstring01(test));
		System.out.println(lengthOfLongestSubstring03(test));
		System.out.println(lengthOfLongestSubstring04(test));
	}
	private static void test04() {
		String test = " ";
		System.out.println(lengthOfLongestSubstring(test));
		System.out.println(lengthOfLongestSubstring01(test));
		System.out.println(lengthOfLongestSubstring03(test));
		System.out.println(lengthOfLongestSubstring04(test));
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章