1. 程式人生 > >LeetCode438題:找到字串中所有字母異位詞

LeetCode438題:找到字串中所有字母異位詞

原始思路1: 獲取p串的全排列,與s暴力對比

但這種方法時間複雜度太高,主要是因為全排列的複雜度太高,如果p字串長度為n的話,那麼全排列複雜度為O(n!)。嚴重超時。

public class Test {
	Set<String> set = new HashSet<String>();
	public static void main(String[] args) {
		String s = "cbadecbabacdcbabdcadbc";
		String p = "abcd";
		Test t = new Test();
		List<Integer> list = t.findAnagrams(s, p);
		for (int i : list) {
			System.out.print(i + " ");
		}
	}

	public List<Integer> findAnagrams(String s, String p) {
		List<Integer> list = new ArrayList<Integer>();
		char[] arr = p.toCharArray();
		fun(arr, 0);
		for (int i = 0; i <= s.length() - p.length(); i++) {
			if (set.contains(s.substring(i, i + p.length()))) {
				list.add(i);
			}
		}
		return list;
	}

	public void fun(char[] arr, int index) {
		if (index == arr.length) {
			set.add(String.valueOf(arr));
			return;
		}
		for (int i = index; i < arr.length; i++) {
			swap(arr, index, i);
			fun(arr, index + 1);
			swap(arr, index, i);
		}
	}

	public void swap(char[] arr, int i, int j) {
		char temp = arr[i];
		arr[i] = arr[j];
		arr[j] = temp;
	}
}

原始思路2:擷取p長度的字串排序比較

思路是先將p進行排序,然後在遍歷s,每次遍歷p個長度,並排序,然後與經過排序的p進行比較。

遺憾的是,也超時了。在測試用例全是一長串“a”的時候,超出了時間限制。

public List<Integer> findAnagrams(String s, String p) {
		List<Integer> list = new ArrayList<Integer>();
        if(s.length() < p.length() || s == null || p == null){
            return list;
        }
		char[] pArr = p.toCharArray();
		Arrays.sort(pArr);
		String strP = String.valueOf(pArr);
		int len = p.length();
		for(int i=0;i<=s.length()-len;i++){
            if(s.substring(i, i+len).equals(p)){
                list.add(i);
            }else{
                char[] sArr = s.substring(i, i+len).toCharArray();
			    Arrays.sort(sArr);
			    if(String.valueOf(sArr).equals(strP)){
				    list.add(i);
			    }
            }
		}
		return list;
    }

正規解法:滑動視窗法

表示沒看太懂。感覺這種方法的關鍵部分是每比較一遍後,在進行下一輪比較前,需要復位。

public List<Integer> findAnagrams(String s, String p) {
		List<Integer> result = new ArrayList<Integer>();
        char[] sArr = s.toCharArray();
        char[] pArr = p.toCharArray();
        int[] word = new int[26];
        for(char ch : pArr){
            word[ch-'a']++;
        }
        int start = 0;
        for(int i=0;i<sArr.length;i++){
            int cIndex = sArr[i]-'a';
            word[cIndex]--;
            while(word[cIndex]<0){
                word[sArr[start]-'a']++;
                start++;
            }
            if(i-start+1 == pArr.length){
                result.add(start);
                word[sArr[start]-'a']++;
                start++;
            }
            
        }
        return result;
    }