当前位置: 首页 > news >正文

剑指 Offer II 033. 变位词组


comments: true
edit_url: https://github.com/doocs/leetcode/edit/main/lcof2/%E5%89%91%E6%8C%87%20Offer%20II%20033.%20%E5%8F%98%E4%BD%8D%E8%AF%8D%E7%BB%84/README.md

剑指 Offer II 033. 变位词组

题目描述

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

注意:若两个字符串中每个字符出现的次数都相同且字符顺序不完全相同,则称它们互为变位词。

 

示例 1:

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

示例 2:

输入: strs = [""]
输出: [[""]]

示例 3:

输入: strs = ["a"]
输出: [["a"]]

 

提示:

  • 1 <= strs.length <= 104
  • 0 <= strs[i].length <= 100
  • strs[i] 仅包含小写字母

 

注意:本题与主站 49 题相同: https://leetcode.cn/problems/group-anagrams/

解法

方法一:哈希表

  1. 遍历字符串,对每个字符串按照字符字典序排序,得到一个新的字符串。
  2. 以新字符串为 key[str]value,存入哈希表当中(HashMap<String, List<String>>)。
  3. 后续遍历得到相同 key 时,将其加入到对应的 value 当中即可。

strs = ["eat", "tea", "tan", "ate", "nat", "bat"] 为例,遍历结束时,哈希表的状况:

keyvalue
"aet"["eat", "tea", "ate"]
"ant"["tan", "nat"]
"abt"["bat"]

最后返回哈希表的 value 列表即可。

时间复杂度 O ( n × k × log ⁡ k ) O(n\times k\times \log k) O(n×k×logk)。其中 n n n k k k 分别是字符串数组的长度和字符串的最大长度。

Python3
class Solution:
    def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
        d = defaultdict(list)
        for s in strs:
            k = ''.join(sorted(s))
            d[k].append(s)
        return list(d.values())
Java
class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        Map<String, List<String>> d = new HashMap<>();
        for (String s : strs) {
            char[] t = s.toCharArray();
            Arrays.sort(t);
            String k = String.valueOf(t);
            d.computeIfAbsent(k, key -> new ArrayList<>()).add(s);
        }
        return new ArrayList<>(d.values());
    }
}
C++
class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        unordered_map<string, vector<string>> d;
        for (auto& s : strs) {
            string k = s;
            sort(k.begin(), k.end());
            d[k].emplace_back(s);
        }
        vector<vector<string>> ans;
        for (auto& [_, v] : d) ans.emplace_back(v);
        return ans;
    }
};
Go
func groupAnagrams(strs []string) (ans [][]string) {
	d := map[string][]string{}
	for _, s := range strs {
		t := []byte(s)
		sort.Slice(t, func(i, j int) bool { return t[i] < t[j] })
		k := string(t)
		d[k] = append(d[k], s)
	}
	for _, v := range d {
		ans = append(ans, v)
	}
	return
}
TypeScript
function groupAnagrams(strs: string[]): string[][] {
    const d: Map<string, string[]> = new Map();
    for (const s of strs) {
        const k = s.split('').sort().join('');
        if (!d.has(k)) {
            d.set(k, []);
        }
        d.get(k)!.push(s);
    }
    return Array.from(d.values());
}
Swift
class Solution {
    func groupAnagrams(_ strs: [String]) -> [[String]] {
        var d = [String: [String]]()

        for s in strs {
            let sortedStr = String(s.sorted())
            if d[sortedStr] == nil {
                d[sortedStr] = [String]()
            }
            d[sortedStr]!.append(s)
        }

        return Array(d.values)
    }
}

方法二:计数

我们也可以将方法一中的排序部分改为计数,也就是说,将每个字符串 s s s 中的字符以及出现的次数作为 key,将字符串 s s s 作为 value 存入哈希表当中。

时间复杂度 O ( n × ( k + C ) ) O(n\times (k + C)) O(n×(k+C))。其中 n n n k k k 分别是字符串数组的长度和字符串的最大长度,而 C C C 是字符集的大小,本题中 C = 26 C = 26 C=26

Python3
class Solution:
    def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
        res=defaultdict(list)
        for s in strs:
            cnt=[0]*26 #strs[i] 仅包含小写字母
            for c in s:cnt[ord(c)-ord("a")]+=1
            res[tuple(cnt)].append(s) # 不可变:tuple(cnt)
        return list(res.values())
Java
class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        Map<String, List<String>> d = new HashMap<>();
        for (String s : strs) {
            int[] cnt = new int[26];
            for (int i = 0; i < s.length(); ++i) {
                ++cnt[s.charAt(i) - 'a'];
            }
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < 26; ++i) {
                if (cnt[i] > 0) {
                    sb.append((char) ('a' + i)).append(cnt[i]);
                }
            }
            String k = sb.toString();
            d.computeIfAbsent(k, key -> new ArrayList<>()).add(s);
        }
        return new ArrayList<>(d.values());
    }
}
C++
class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        unordered_map<string, vector<string>> d;
        for (auto& s : strs) {
            int cnt[26] = {0};
            for (auto& c : s) ++cnt[c - 'a'];
            string k;
            for (int i = 0; i < 26; ++i) {
                if (cnt[i]) {
                    k += 'a' + i;
                    k += to_string(cnt[i]);
                }
            }
            d[k].emplace_back(s);
        }
        vector<vector<string>> ans;
        for (auto& [_, v] : d) ans.emplace_back(v);
        return ans;
    }
};
Go
func groupAnagrams(strs []string) (ans [][]string) {
	d := map[[26]int][]string{}
	for _, s := range strs {
		cnt := [26]int{}
		for _, c := range s {
			cnt[c-'a']++
		}
		d[cnt] = append(d[cnt], s)
	}
	for _, v := range d {
		ans = append(ans, v)
	}
	return
}

相关文章:

  • 本地部署语言大模型deepseek完整步骤
  • 软件供应链安全工具链研究系列——RASP自适应威胁免疫平台(上篇)
  • esp8266 rtos sdk开发环境搭建
  • 使用 Python 实现声纹和声音识别并集成到会议记录程序中
  • 蓝牙的baseProfile和ble模块有什么区别
  • 139.单词拆分
  • 人类驾驶的人脑两种判断模式(反射和预判)-->自动驾驶两种AI模式
  • kubernetes 初学命令
  • 记一次pytorch训练loss异常的问题
  • LinkedList与链表
  • (学习总结26)Linux工具:make/Makefile 自动化构建、Git 版本控制器 和 gdb/cgdb 调试器
  • 鸿蒙-状态管理V2其他方法
  • 评高级工程师职称的条件-三大硬性要求
  • 【时时三省】(C语言基础)数据类型
  • Linux通过设备名称如何定位故障硬盘
  • 应用的负载均衡
  • windbg-记一次应用程序崩溃的定位
  • 【综合项目】api系统——基于Node.js、express、mysql等技术
  • 穷举vs暴搜vs深搜vs回溯vs剪枝(典型算法思想)—— OJ例题算法解析思路
  • 【java进阶】java多态深入探讨
  • 光明日报社论:用你我的匠心,托举起繁盛的中国
  • 中国代表:美“对等关税”和歧视性补贴政策严重破坏世贸规则
  • 中国建设银行浙江省分行原党委书记、行长高强接受审查调查
  • 卡尼领导的加拿大自由党在联邦众议院选举中获胜
  • 日月谭天丨赖清德强推“脱中入北”是把台湾带向死路
  • “五一”假期全国口岸日均出入境人员将达215万人次