先看原题
题目给的中等,其实也就比上一篇博客发的那个略微难一点而已。
一、那这里先介绍一个超好用的方法:sort(),算法题里应该可以使用吧。
sort()
是 C++ 标准库中的一个排序函数,可以快速将数组、容器(如 vector
)中的元素按照你想要的顺序排列。例如:
- 将
[3,1,4,2]
排序为[1,2,3,4]
(升序) - 将
["banana", "apple"]
排序为["apple", "banana"]
(字典序)
所以你看,这玩意多智能?
基本语法:
#include <algorithm> // 必须包含这个头文件
using namespace std; // 使用标准命名空间
sort(起始地址, 结束地址的下一位, 比较函数(可选));
- 起始地址:要排序的第一个元素的位置(指针或迭代器)
- 结束地址的下一位:要排序的最后一个元素的下一个位置
- 比较函数(可选):自定义排序规则,默认是升序
举例说明:
#include <iostream>
#include <algorithm> // 引入头文件
using namespace std;
int main()
{
int arr[] = {3, 1, 4, 2};
int n = sizeof(arr) / sizeof(arr[0]); // 计算数组长度
sort(arr, arr + n); // 排序:起始地址是arr,结束地址是arr+n
// 输出结果:1 2 3 4
for (int i = 0; i < n; i++) {
cout << arr[i] << " ";
}
return 0;
}
随便定义一个数组,然后计算一下数组的长度
这里使用sort排序,默认升序。
注意,里面传入的一定是地址!
输出一定是1,2,3,4.
以下注意:
-
arr
是数组首地址,arr + n
是最后一个元素的下一位地址。 -
sort(arr, arr + n)
表示对整个数组升序排序。
ok这下我们有了个巨好用的工具了。那么就很简单了。
这题你看,有没有可能,我们先给他排个序?是把每一个字符串都给他排个序?
这里再次说明一个东西叫C风格字符串,如果是常量的话可以简单理解为一个叫const char* 数组。
就是一个字符数组不就是一个字符串嘛,字面意思。
诶,那么对于每一个在原本的大数组的元素:
进来后给这个字符串自己排序(C风格字符串)
排序后,这不就齐活了吗?
所有的元素都是统一的格式,但是每一个人的顺序都没乱,那么接下来就简单了。
在刚才排序后定义一个保存结果的数组,这个数组的形式在题解的那个函数类型已经给了提示,
是一个以vector<string>为元素类型的vector数组。用来保存重新匹配配对后的结果。
这里还有个马后炮,在前面那个给每一个元素排序的时候,按照key,把元素也塞进去
key:组成这个元素的字母组合,也就是排序后的字符串
value:这个元素自己,没排序的值
所以很明显前面得有一个东西拷贝原本的元素,然后那这个拷贝的排序,排序完后根据这个拷贝,作为key,把本尊作为value放进哈希表。
然后呢,再把哈希表的value给到result。
我知道这个时候可能就有人要问了,主包主包,你的哈希表为什么一个key值能有多个value
有没有可能,那个哈希表的value,其实是一个数组?
狗头。
后面还有一点:那就是把value pop出来的时候记得用move()
虽然我也不懂为啥,但是好像说很厉害的样子。
完整代码如下:
vector<vector<string>> groupAnagrams(vector<string>& strs) {
// 创建哈希表,键是排序后的字符串,值是分组列表
unordered_map<string, vector<string>> groups;
// 遍历所有字符串
for (const string& s : strs) {
// 对当前字符串排序生成键
string key = s; // 复制原字符串
sort(key.begin(), key.end()); // 排序字符
// 将原始字符串加入对应分组
groups[key].push_back(s);
}
// 收集所有分组到结果中
vector<vector<string>> result;
for (auto& pair : groups) { // pair 是键值对
result.push_back(std::move(pair.second)); // 移动语义优化
}
return result;
}
函数定义
cpp
vector<vector<string>> groupAnagrams(vector<string>& strs) {
- 输入参数是字符串数组的引用
strs
。 - 返回值是二维字符串数组,表示分组后的结果。
3. 创建哈希表
cpp
unordered_map<string, vector<string>> groups;
groups
的键是排序后的字符串(string
),值是对应的分组列表(vector<string>
)。
4. 遍历所有字符串
cpp
for (const string& s : strs) {
- 使用范围 for 循环逐个处理输入字符串
s
。
5. 生成排序后的键
cpp
string key = s; // 复制原字符串
sort(key.begin(), key.end());
- 将原字符串复制到
key
(避免直接修改原字符串)。 - 对
key
的字符排序(例如 "tea" → "aet")。
6. 将字符串加入分组
cpp
groups[key].push_back(s);
- 以
key
为键,将原字符串s
添加到对应的分组列表中。 - 如果
key
不存在,unordered_map
会自动创建一个空列表。
7. 收集所有分组到结果
cpp
vector<vector<string>> result;
for (auto& pair : groups) {
result.push_back(std::move(pair.second));
}
result
是最终返回的分组列表。- 遍历哈希表的每个键值对
pair
,将分组列表pair.second
移动到result
中。 - 移动语义优化:
std::move
避免复制整个vector
,提高效率。
三、总结关键内容
1.sort();
2.unordered_map()
3.move()