字符串处理:字母异位词分组

字母异位词分组

题目描述:给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。字母异位词 是由重新排列源单词的字母得到的一个新单词,所有源单词中的字母通常恰好只用一次。

解法一:暴力/哈希表
简单的暴力算法,题目要求是字母异或词,也就是说异或词的每个字母是相同的,只不过排列的顺序不一样。基于这个,我的想法是:将每个词进行一次排列,那么互为字母异或词的单词经过排列后一定是相等的。所以,先复制一遍输入的词,将他里面的每个词进行一次排序,然后依次找到相同的单词的坐标,把相同的单词加入结果即可得到答案。
步骤:
1、将各个字符串排序
2、遍历每个字符串
3、寻找相同的字符串,并记录下标
4、将相同的字符串添加到结果里

class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        vector<string> temp = strs;
        vector<vector<string>> groudWords;
        int len = strs.size();
        int *visited = new int[len];
        if(len == 0) return groudWords;

        for(int i = 0; i < len; i++)
        {
            sort(temp[i].begin(), temp[i].end());
        }

        for(int i = 0; i < len; i++)
        {
            if(visited[i] == 1)
            {
                continue;
            }
            groudWords.push_back(attemdGroudWords(temp, strs, i, visited));
        }
        return groudWords;
    }

    vector<string> attemdGroudWords(vector<string>& temp, vector<string>& strs, int index, int* visited)
    {
        vector<string> groudWord;
        for(int i = index; i < temp.size(); i++)
        {
            if(temp[i] != temp[index] || visited[i] == 1)
            {
                continue;
            }
            visited[i] = 1;
            groudWord.push_back(strs[i]);
        }
        return groudWord;
    }
};

这是我第一次的解法,提交后发现时间复杂度度太大了,关是将每个单词排序的时间复杂度都需要O(n*m)(n是单词数,m是单词的长度)。后来我看了答案发现可以用哈希表进行优化。

class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        unordered_map<string, vector<string>> mp;
        vector<vector<string>> combineWordGroups;
        int len = strs.size();
        if(len == 0)
            return combineWordGroups;
        
        for(int i = 0; i < len; i++)
        {
            string str = strs[i];
            sort(str.begin(), str.end());
            mp[str].push_back(strs[i]);
        }
        int mpLen = mp.size();
        for(unordered_map<string, vector<string>>::iterator it = mp.begin(); it != mp.end(); it++)
        {
            combineWordGroups.push_back(it->second);
        }
        return combineWordGroups;
    }
};

优化后时间复杂度变为O(nklogk),其中n是单词的数量,k是strs中的字符串的最大长度。
解法二:数值替代法。
这个是我在评论区看到的解法,感觉挺有意思的就记录下来了。首先将每个字母定义一个数字,比如a对应的就是1,d对应的是2…,由于互为异或词的单词组成是相同的,那么这两个单词所组成的字母的数字和也一定是相同的,也就是说"abc"和"bca"互为异或词,"abc"对应的数值是1+2+3=6,"bca"对应的数值是2+3+1=6。基于这个规律就可以解出来了。

反思
这道题虽然写对了,思路也和正确答案一样,但是写出来的时间复杂度太高了,没有用最正确的代码将思路表达出来。原因是对数据结构不熟悉,没有一开始就想到哈希表。以后写题的时候会优先考虑数据结构。

你可能感兴趣的:(算法,c++)