力扣热题100-哈希表:字母异位词分组

题目描述:

题号:49

题目描述:

给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。

字母异位词 是由重新排列原单词的所有字母得到的一个新单词。

边界条件:

  • 1 <= strs.length <= 104

  • 0 <= strs[i].length <= 100

  • strs[i] 仅包含小写字母

示例 :

输入: strs = ["eat", "tea", "tan", "ate", "nat", "bat"]
输出: [["bat"],["nat","tan"],["ate","eat","tea"]]

解题思路:

思路一:对每个单词进行排序+哈希表

互为字母异位词的两个字符串的特征:包含的字母相同。

因此想到对两个字符串分别进行排序之后得到的字符串也是相同的。因此可以利用排序后的字符串统计字母异位词:将排序之后的字符串作为哈希表的键,原字符串作为哈希表的值。

K为字符串平均大小,N为字符串数量

时间复杂度:O(N*KlogK):排序算法有KlogK时间复杂度

空间复杂度:O(K*N)

C++

// C++
class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        if(strs.size() == 0) {
            return {};
        }
        unordered_map<string, vector<string>> subMap;
        for(string &value : strs) {
            string key = value;
            // 字母异位词根据字符排序后的字符串是相同的
            sort(key.begin(), key.end());
            // 以排序后的词作为map的key
            subMap[key].push_back(value);
        }
        vector<vector<string>> result;
        for(auto item = subMap.begin(); item != subMap.end(); item++) {
            result.push_back(item->second);
        }
        return result;
    }
};

go

// go
func groupAnagrams(strs []string) [][]string {
    if len(strs) == 0 {
        return nil
    }
    subMap := map[string][]string{}
    for _, v := range strs {
        vByte := []byte(v)
        sort.Slice(vByte, func(i, j int) bool {return vByte[i] < vByte[j]})
        sortKey := string(vByte)
        subMap[sortKey] = append(subMap[sortKey], v)
    }

    result := make([][]string, 0, len(subMap))
    for _, v := range subMap {
        result = append(result, v)
    }
    return result
}

思路二:哈希

第二种思路是将字符串中会出现的26个小写字母像哈希映射一样映射到一个string对象中,映射相同的字符串具有相同数量的每种字母,因此必定是字母异位词

时间复杂度:O(K*N)

空间复杂度:O(K*N)

C++


// C++
class Solution{
private:
    string getKeyHash(const string &str) {
        // 统计每个字符串中的每个字符出现的数量
        string Hash(26, 0);
        for(const char &ch : str) {
            Hash[ch - 'a']++;
        }
        return Hash;
    }

public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        if(strs.size() == 0) {
            return {};
        }

        unordered_map<string, vector<string>> subMap;
        for(const auto &str : strs) {
            subMap[getKeyHash(str)].push_back(str);
        }

        vector<vector<string>> result;
        for(const auto &item : subMap) {
            result.push_back(item.second);
        }

        return result;
    }
};

go


// go
func groupAnagrams(strs []string) [][]string {
    if len(strs) == 0 {
        return nil
    }
    subMap := make(map[string][]string)  
  for _, str := range strs {  
    key := getKeyHash(str)  
    subMap[key] = append(subMap[key], str)  
  }  
  
  var result [][]string  
  for _, group := range subMap {  
    result = append(result, group)  
  }  
  
  return result  
}

func getKeyHash(str string) string {  
  // 统计每个字符串中的每个字符出现的数量  
  hash := make([]int, 26)  
  for _, ch := range str {  
    if ch >= 'a' && ch <= 'z' {  
      hash[ch-'a']++  
    }  
  }  
  
  // 将字符计数转换为字符串,用作哈希键  
  var sb strings.Builder  
  for _, count := range hash {  
    sb.WriteString(strconv.Itoa(count))  
    sb.WriteString("#")  
  }  
  return sb.String()  
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值