(程式設計題)字母易位詞
阿新 • • 發佈:2018-11-28
題目
兩個單詞如果包含相同的字母,次序不同,則稱為字母易位詞(anagram)。例如,“silent”和“listen”是字母易位詞,而“apple”和“aplee”不是易位詞。請定義函式檢查兩個單詞是否是字母易位詞。可以假設兩個單詞字母均為小寫。要求演算法複雜度儘量低。
思路
- 1.暴力破解:判斷str1中的每一個字母是否出現在str2中,同時我們需要一個大小與字串位數一致的陣列來記錄str2中已經被標記的位。
public static boolean compare(String str1, String str2) { int i,j; if (str1 == null && str2 == null) { return true; } if ((str1 == null && str2 != null) || (str1 != null && str2 == null) || str1.length() != str2.length()) { return false; } // boolean 預設是false boolean[] flags = new boolean[str2.length()]; for (i = 0; i < str1.length(); i++) { char temp = str1.charAt(i); for (j = 0; j < str2.length(); j++) { if (str2.charAt(j) == temp && !flags[j]) { flags[j]=true; break; } } if(j>=str2.length()){ return false; } } return true; }
我們可以看到用到兩個for迴圈,一個會遍歷n次,裡層for迴圈我們假設最壞的情況是每次都走到最後一位(比如world和dlrow),那麼裡面的次數是n,n-1,n-2…1,複雜程度為
n(n-1)/2=1/2*n^2+1/2*n=O(n^2)
- 2.是否可以先排序再一一比較就可以了,比較的時候最多是n次,那麼我們的排序演算法如果能降低複雜度的話,這也是一個好辦法。
public static boolean compare2(String str1,String str2){ if (str1 == null && str2 == null) { return true; } if ((str1 == null && str2 != null) || (str1 != null && str2 == null) || str1.length() != str2.length()) { return false; } char[] str1ToChar = str1.toCharArray(); Arrays.sort(str1ToChar); char[] str2ToChar = str2.toCharArray(); Arrays.sort(str2ToChar); for(int i=0;i<str1.length();i++){ if(str1ToChar[i]!=str2ToChar[i]){ return false; } } return true; }
我們知道java提供的排序演算法複雜度是O(n*logn),兩次排序加上比較:
2*O(n*logn)+n
- 3.我們希望能進一步減低演算法複雜度,於是想到一個計數器,找到26大小的陣列來記錄每一個字母出現的次數,遍歷第一個陣列的時候,個數不斷增加,遍歷第二個陣列的時候,不斷減少,如果最後是0,就證明兩個字串中字元出現的次數都是一樣的。
public static boolean compare(String str1,String str2){ if (str1 == null && str2 == null) { return true; } if ((str1 == null && str2 != null) || (str1 != null && str2 == null) || str1.length() != str2.length()) { return false; } int[] num = new int[26]; for(int i=0;i<str1.length();i++){ num[str1.charAt(i)-'a']++; } for(int i=0;i<str2.length();i++){ num[str2.charAt(i)-'a']--; } for(int i=0;i<num.length;i++){ if(num[i]!=0){ return false; } } return true; }
我們可以看到這個演算法中,遍歷兩次字串2*n,又遍歷一次m(m<=n).
所以演算法的複雜度是:
2*n+m=O(n)
總結:其實裡面沒有什麼深奧的演算法,只是一些小技巧,用空間來換取時間,一開始不比較,而是將字串的異同表現在字元出現的個數上,這樣子,問題就迎刃而解了。