1. 程式人生 > 實用技巧 >【Leetcode】49.字母異位分詞

【Leetcode】49.字母異位分詞

題目連結

49. 字母異位詞分組

題目描述

解題思路

1.暴力法

兩個for迴圈,分別判斷兩個字串出現的字母個數是否相同,相同加入同一個List。時間複雜度基本等於O(n^2),Leetcode上提交是超時的。

2.hash法

對暴力法進行改進,利用List記錄字串出現的字母個數相同的字串,同時利用hash表記錄List在ans二維列表的下標,這樣只需要遍歷一遍陣列即可。

問題來了:hash表的值是下標,那hash表的鍵值該如何表示?

利用大小為26的陣列,並初始化值為-1,統計每個字母出現的次數,如果兩個字串符合要求,那麼兩個字串對應的陣列一定是相同的,所以由陣列值轉換成的字串也一定是相同的。所以hash表的鍵值為陣列值轉換成的字串

3.利用質數實現hash法

解法思路與2相同,首先為26個字元賦值為26個質數,因為質數與質數的乘積是唯一的,這符合hash表鍵值的要求。所以hash表的鍵值為對應字母的質數乘積。

AC程式碼

1.暴力法

class Solution {
    public int[] cal(String temp,int[] count){
        for(int i = 0; i < temp.length(); i++){
            count[temp.charAt(i)-'a']++;
        }
        return count;
    }
    public boolean test(int[] countA,int[] countB){
        for(int i = 0; i < 26; i++){
            if(countA[i] != countB[i]) return false;
        }
        return true;
    }
    public List<List<String>> groupAnagrams(String[] strs) {
        List<List<String>> ans = new LinkedList<>();
        boolean flags[] = new boolean[strs.length];
        for(int i = 0; i < strs.length; i++){
            if(flags[i] == true) continue;
            List<String> temp = new LinkedList<>();
            int countA[] = new int[26];
            countA = cal(strs[i],countA);
            temp.add(strs[i]);
            for(int j = i + 1; j < strs.length; j++){
                int countB[] = new int[26];
                countB = cal(strs[j],countB);
                if(test(countA,countB)){
                    temp.add(strs[j]);
                    flags[j] = true;
                }
            }
            ans.add(temp);
        }
        return ans;
    }
}

2.hash表法

class Solution {

    public String count(String temp,int[] tot){
        StringBuffer sb = new StringBuffer();
        for(int i = 0; i < temp.length(); i++){
            tot[temp.charAt(i)-'a']++;
        }
        for(int i = 0; i < tot.length; i++) sb.append(tot[i]);
        return sb.toString();
    }

    public List<List<String>> groupAnagrams(String[] strs) {
        List<List<String>> ans = new LinkedList<>();
        Map<String,Integer> hashTable = new HashMap<>();
        for(int i = 0; i < strs.length; i++){
            int[] countN = new int[26]; 
            Arrays.fill(countN,-1);
            String str = count(strs[i],countN);
            if(hashTable.containsKey(str)){
                int index = hashTable.get(str);
                ans.get(index).add(strs[i]);
            }else{
                List<String> temp = new LinkedList<>();
                temp.add(strs[i]);
                ans.add(temp);
                hashTable.put(str,ans.size()-1);               
            }
        }
        return ans;
    }
}

3.利用質數實現hash法

class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        vector<vector<string>> res;
        unordered_map <double,vector<string> > m;
        double a[26]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101};
        for(string& s : strs)
        {
            double t = 1;
            for(char c : s)
                t *= a[c - 'a'];
            m[t].push_back(s);          //t為單詞對應的質數乘積,m[t]則為該單詞的異位詞構成的vector
        }
        for(auto& n : m)                //n為鍵和值組成的pair
            res.push_back(n.second);
        return res;
    }
};