📝前言说明:
- 本专栏主要记录本人的基础算法学习以及LeetCode刷题记录,按专题划分
- 每题主要记录:(1)本人解法 + 本人屎山代码;(2)优质解法 + 优质代码;(3)精益求精,更好的解法和独特的思想(如果有的话)
- 文章中的理解仅为个人理解。如有错误,感谢纠错
🎬个人简介:努力学习ing
📋本专栏:C++刷题专栏
📋其他专栏:C语言入门基础,python入门基础,C++学习笔记,Linux
🎀CSDN主页 愚润泽
你可以点击下方链接,进行该专题内不同子专题的学习
| 点击链接 | 开始学习 |
|---|---|
| 双指针(1) | 双指针(2) |
| 双指针(3) | 双指针(4) |
| 滑动窗口(1) | 滑动窗口(2) |
| 滑动窗口(3) | 滑动窗口(4) |
| 二分查找(1) | 二分查找(2) |
| 前缀和(1) | 前缀和(2) |
| 前缀和(3) | 位运算(1) |
| 位运算(2) | 模拟算法 |
| 快速排序 | 归并排序 |
| 链表 | 哈希表 |
| 字符串 | 栈 |
| 队列 + 宽搜 | 优先级队列 |
| BFS 解决 FloodFill | BFS 解决最短路径 |
| 多源 BFS | BFS 解决拓扑排序 |
题单汇总链接:点击 → 题单汇总(暂时未整理,因为还没刷完)
导论
- 哈希表理论:映射(哈希函数,又涉及哈希冲突…)
- 哈希表是一个存储数据的容器,查找速度 O ( 1 ) O(1) O(1)
- 当需要快速查找某个元素的时候 → 使用哈希表(或者二分 O ( l o g N ) O(logN) O(logN))
- 使用哈希表
- 自带的:unordered_map
- 使用数组模拟
<index, a[index]>(好映射且数据范围小的,有负数索引的时候不建议用)
1. 两数之和
题目链接:https://leetcode.cn/problems/two-sum/description/

个人解
代码:
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target)
{
unordered_map<int, int> hash; // <元素, 下标>
for(int i = 0; i < nums.size(); i++)
{
int x = target - nums[i];
if(hash.count(x)) return {hash[x], i};
hash[nums[i]] = i; // 会覆盖
}
// 编译器要求必须返回
return {-1, -1};
}
};
时间复杂度:
O
(
n
)
O(n)
O(n)
空间复杂度:
O
(
n
)
O(n)
O(n)
面试题 01.02. 判定是否互为字符重排
题目链接:https://leetcode.cn/problems/check-permutation-lcci/description/

个人解
思路:
- 很妙:一个
+一个-,并且在-修改哈希表的时候就直接判断是否满足要求
屎山代码:
class Solution {
public:
bool CheckPermutation(string s1, string s2) {
int m = s1.size(), n = s2.size();
if(m != n) return false;
int hash[26];
for(auto c: s1)
hash[c - 'a']++;
for(auto c: s2)
if(--hash[c - 'a'] < 0)
return false;
return true;
}
};
时间复杂度:
O
(
n
)
O(n)
O(n)
空间复杂度:
O
(
1
)
O(1)
O(1)
217. 存在重复元素
题目链接:https://leetcode.cn/problems/contains-duplicate/description/

个人解
屎山代码:
class Solution {
public:
bool containsDuplicate(vector<int>& nums) {
unordered_map<int, int> hash; // <数字, 次数>
for(auto x: nums)
if(++hash[x] >= 2)
return true;
return false;
}
};
时间复杂度:
O
(
n
)
O(n)
O(n)
空间复杂度:
O
(
n
)
O(n)
O(n)
219. 存在重复元素 II
题目链接:https://leetcode.cn/problems/contains-duplicate-ii/description/

个人解
屎山代码:
class Solution {
public:
bool containsNearbyDuplicate(vector<int>& nums, int k)
{
unordered_map<int, int> hash; // 记录某个数字最近一次出现的索引
for(int i = 0; i < nums.size(); i++)
{
int x = nums[i];
if(hash.count(x) && (i - hash[x] <= k))
return true;
hash[x] = i; // 如果是第一次出现或者不符合,则 添加/ 更新索引
}
return false;
}
};
时间复杂度:
O
(
n
)
O(n)
O(n)
空间复杂度:
O
(
n
)
O(n)
O(n)
49. 字母异位词分组
题目链接:https://leetcode.cn/problems/group-anagrams/description/

个人解
屎山代码:
超时了,时间复杂度:
O
(
n
2
)
O(n^2)
O(n2)
class Solution {
public:
bool is_yiwei(string& a, string& b)
{
vector<int> hash(26, 0);
int m = a.size(), n = b.size();
if(m != n) return false;
for(auto x: a)
hash[x - 'a']++;
for(auto x: b)
if(--hash[x - 'a'] < 0)
return false;
return true;
}
vector<vector<string>> groupAnagrams(vector<string>& strs)
{
// 将哈希表相同的字符串放在一个 vector 里面
int n = strs.size();
vector<bool> check(n, false); // 记录当前的字符串有没有被放入
vector<vector<string>> ans;
for(int i = 0; i < n; i++) // strs[i] 是基准
{
if(check[i]) continue; // 说明当前的基准已经和前面的基准匹配过了
vector<string> path;
path.emplace_back(strs[i]);
for(int j = i + 1; j < n; j++)
{
if(is_yiwei(strs[i], strs[j]))
{
path.emplace_back(strs[j]);
check[j] = true;
}
}
ans.emplace_back(path);
}
return ans;
}
};
优质解
思路:
- 对于两个词,我们如何判断是不是异位词?
- 方法一:相同异位词对应的哈希表相同(可是哈希表的键不能是哈希表)
- 方法二:相同的异位词
sort以后是相同的字符串
- 把容器进行组合,哈希表:
<string, vector<string>>string是排序后的字符串vector<string>是异位词的一组- 我们通过把异位词排序找到要添加的
vector,然后把原来的异位词加进去
代码:
class Solution {
public:
vector<vector<string>> groupAnagrams(vector<string>& strs)
{
unordered_map<string, vector<string>> hash;
for(auto s:strs)
{
string tmp = s;
sort(tmp.begin(), tmp.end());
hash[tmp].emplace_back(s);
}
vector<vector<string>> ans;
for(auto p:hash)
ans.emplace_back(p.second);
return ans;
}
};
时间复杂度:
O
(
N
∗
K
l
o
g
K
)
)
O(N*KlogK))
O(N∗KlogK)), N 是字符串数量,K是字符串长度
空间复杂度:
O
(
N
∗
K
)
O(N*K)
O(N∗K)
🌈我的分享也就到此结束啦🌈
要是我的分享也能对你的学习起到帮助,那简直是太酷啦!
若有不足,还请大家多多指正,我们一起学习交流!
📢公主,王子:点赞👍→收藏⭐→关注🔍
感谢大家的观看和支持!祝大家都能得偿所愿,天天开心!!!


814

被折叠的 条评论
为什么被折叠?



