力扣hot100 -- 哈希

目录

🌼两数之和

暴力

二分

哈希

🌼字母异位词分组

unordered_map + 排序

unordered_map + 计数

🌼最长连续序列

unordered_set + 跳过前驱

排序 + dp


🌼两数之和

1. 两数之和 - 力扣(LeetCode)

暴力

O(n^2)  两层循环

class Solution {
public:vector<int> twoSum(vector<int>& nums, int target) { // 返回vector数组int n = nums.size();for (int i = 0; i < n - 1; ++i)for (int j = i + 1; j < n; ++j) if (nums[i] + nums[j] == target)    return {i, j};return {}; // 返回空数组}
};

二分

O(nlogn)

O(nlogn)    整数二分      整数二分需要注意边界,防止下取整的坑(死循环)

排序 O(nlogn) 

外层for  O(n)   *    for 循环里二分 O(logn)     =   O(nlogn)

详细解释下第 32 行

if (a[i].x == a[l].x) l++; // 避免同一个元素, 索引++(最关键)

比如 i == 2, l == 4,2 + 4 == 6,而假设此时双方的值都是3,3 + 3 == 6

那么就会输出同一个元素的下标,需要索引 + 1

AC  代码

#include<algorithm> // sort()
using namespace std;struct node {int v, x; // value 和 index
}a[10010];bool cmp(node x, node y)
{return x.v < y.v;
}class Solution {
public:vector<int> twoSum(vector<int>& nums, int target) {int n = nums.size();for (int i = 0; i < n; ++i)a[i].v = nums[i], a[i].x = i; // 先结合sort(a, a + n, cmp); // 再排序(结构体数组)// 遍历for (int i = 0; i < n; ++i) {int l = 0, r = n - 1;while (l < r) { // 二分int m = (l + r) >> 1;if (a[m].v >= target - a[i].v) // target - a[i].v 为要查找的值r = m;elsel = m + 1;}// 退出 while 后, l == rif (a[i].v + a[l].v == target) {if (a[i].x == a[l].x) l++; // 避免同一个元素, 索引++(最关键)return {a[i].x, a[l].x}; // 返回下标}}return {}; // 返回空数组}
};

哈希

O(n)

知识

map<string, int>a; //升序
map<string, int, greater<string> >a; //降序h[key] = val;
//等价于
h.insert(make_pair(key, val));for(map<string, int>::iterator it = a.begin(); it != a.end(); ++it)cout<<it->first<<"\t"<<it->second<<endl;
size/empty/clear //元素个数,判空,清空
begin / end //指向开始 / 结束位置的指针
insert(x) //将元素x插入集合(x为二元组)
erase(x) //删除所有等于x的元素(x为二元组)
erase(it) //删除it指向的元素(it为指向二元组的迭代器)
find(k) //查找键为k的二元组的位置, 若不存在, 返回尾指针 .end()

C++ map和unordered_map详解-腾讯云开发者社区-腾讯云 (tencent.com)

AC  代码

class Solution {
public:vector<int> twoSum(vector<int>& nums, int target) { // 返回vector数组int n = nums.size();unordered_map<int, int> h; // 键 元素大小;值 元素下标for (int i = 0; i < n; ++i) {auto it = h.find(target - nums[i]); // 查找这个键 -- 元素大小if (it != h.end()) // 找到了该元素return {i, it->second}; // 返回下标//h.insert(make_pair(nums[i], i)); // 插入键值对h[nums[i]] = i; // 插入键值对}return {}; // 返回空数组}
};

🌼字母异位词分组

49. 字母异位词分组 - 力扣(LeetCode)

知识

1)emplace_back 与 push_back

一文弄清楚 push_back 和 emplace_back 的区别-emplace_back和push_back有区别吗 (51cto.com)

2)unordered_map 与 map

map和unordered_map区别及其优缺点 - 己平事 - 博客园 (cnblogs.com)

map、multimap 容器都会自行根据的大小对存储的键值对进行排序 

3)代码中,两个要注意的点

(一)引用传递 比 迭代器 快很多(访问vector<string>时)

// 引用传递
for (string& str : strs) // 迭代器
for (vector<string>::iterator it = strs.begin(); it != strs.end(); ++it)

(二)emplace_back 比 push_back 快 20%

unordered_map + 排序

O(n*k*logk)      n -- strs中字符串数量    k 单个字符串最大长度    ≈  5*1e6

class Solution {
public:vector<vector<string>> groupAnagrams(vector<string>& strs) {unordered_map<string, vector<string> > s; // 键 string  值 vector<string>vector<vector<string> > ans; // 返回类型// 遍历字符串数组 strsfor (string& str : strs) { // 引用传递 快很多string key = str;sort(key.begin(), key.end());s[key].push_back(str);}// for (vector<string>::iterator it = strs.begin(); it != strs.end(); ++it) {//     string key = *it; // 键//     sort(key.begin(), key.end()); // 对键排序//     s[key].push_back(*it); // 键 -- 排序后的值// }for (auto t : s) ans.push_back(t.second); // 插入vector<string>类型数组// for (auto it = s.begin(); it != s.end(); ++it)//     ans.push_back(it->second);return ans;}
};

unordered_map + 计数

O(n*k)

排序  -->  计数,变相得到了每个字符串按字典序的排序(隐含的是:int 和 char 之间的

隐式转换

但是有个疑问,如果一个字母出现100次,' ' + 100 == 132,超过了ASCII的127范围,超过范围阶段,可能和前面的冲突才对

可能是样例太少了

注意:& 比 不用&,快很多,避免将元素的值复制到新的变量中

class Solution {
public:vector<vector<string>> groupAnagrams(vector<string>& strs) {// 键--已排序字符串      值--未排序字符串 组成的数组unordered_map<string, vector<string> > s;vector<vector<string> > ans; // 数组元素为 vector<string>for (string& str : strs) { // str 每个字符串// string count = string(26, ' '); string count(26, ' ');for (char& c : str) // c 一个字符count[c - 'a']++;s[count].push_back(str); // 插入键值对}for (auto& t : s) // t--unordered_map<string, vector<string>> 类型ans.push_back(t.second); // 插入 vector<string> 类型return ans;}
};

🌼最长连续序列

128. 最长连续序列 - 力扣(LeetCode)

知识 

size/empty/clear //元素个数  判空  清空
begin/end //开始和结束位置
inset(x) //元素x插入集合
erase(x) //删除所有值为x的元素
erase(it) //删除it迭代器指向的元素
find(x) //查找x在集合的位置,不存在则返回end
count(x) //统计x元素的个数
lower_bound(x) //返回大于等于x的最小元素位置
upper_bound(x) //返回大于x的最小元素位置

思路

set 用于去重

unordered_set,不需要有序,所以用 unordered

存在前驱则跳过

unordered_set + 跳过前驱

O(n)

外层循环 for,因为“存在前驱,则跳过”,数组中每个数,只会进入 内层 while 循环 1 次

所以外层 O(n),内层 O(1)

class Solution {
public:int longestConsecutive(vector<int>& nums) {int ans = 0; // 初始0 有可能空数组unordered_set<int> s; // 去重for (const int& num : nums) // 引用传递s.insert(num);for (auto& num : s) { // 遍历哈希表if (s.count(num - 1)) continue; // 存在前驱 -- 跳过当前int currentNum = num, currentLen = 1; // 当前长度 1while (s.count(currentNum + 1)) {currentLen++; // 长度 +1currentNum++; // 值 +1}ans = max(ans, currentLen);}return ans;}
};

排序 + dp

很好奇,为什么 O(nlogn) 的复杂度,要比上面的 O(n) 快得多........

class Solution {
public:int longestConsecutive(vector<int>& nums) {if (!nums.size()) return 0; // 避免空数组sort(nums.begin(), nums.end()); // 先排序vector<int> nums2;nums2.push_back(nums[0]);for (int i = 1; i < nums.size(); ++i) if (nums[i] != nums[i - 1]) // 再去重nums2.push_back(nums[i]); int n = nums2.size(), ans = 1;if (n == 0) return 0; // 避免空数组vector<int> dp(n, 1); // 初始化for (int i = 1; i < n; ++i) {if (nums2[i] == nums2[i - 1] + 1)dp[i] = dp[i - 1] + 1;ans = max(ans, dp[i]);}return ans;}
};/*
含义:dp[i] 以第 i 个数结尾的最大长度(下标 0 开始)
递推式:if (nums[i] == nums[i - 1] + 1) dp[i] = dp[i - 1] + 1;
初始化:dp[0...n-1] = 1
遍历顺序:nums[]  0...n-1
打表检查
*/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/465496.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Mom系统初步认知

什么是MOM系统? MOM指制造运营管理,是Manufacturing Operation Management的缩写;指通过协调管理企业的人员、设备、物料和能源等资源,把原材料或零件转化为产品的活动。MOM系统集成了生产计划、库存管理、生产调度、质量管理、设备维护、人员管理等功能,以实现生产效率和…

前后端分离好处多多,怕就怕分工不分人,哈哈

前后端分离倡导多年了&#xff0c;现在基本成为了开发的主流模式了&#xff0c;贝格前端工场承接的前端项目只要不考虑seo的&#xff0c;都采用前后端分离模式&#xff0c;这篇文章就来介绍一下前后端分离模式。 一、什么是前后端分离开发模式 前后端分离是一种软件开发的架构…

中国电子学会2019年12月份青少年软件编程Scratch图形化等级考试试卷三级真题(选择题、判断题)

一、单选题(共 25 题&#xff0c;每题 2 分&#xff0c;共 50 分) 1.怎样修改图章的颜色&#xff1f;&#xff08; &#xff09; A. 只需要一个数字来设置颜色 B. 设置 RGB 的值 C. 在画笔中设置颜色、饱和度、亮度 D. 在外观中设置或修改角色颜色特效 2.以下程序的执…

根据三维点坐标使用matplotlib绘制路径轨迹

需求&#xff1a;有一些点的三维坐标&#xff08;x&#xff0c;y&#xff0c;z&#xff09;&#xff0c;需要绘制阿基米德螺旋线轨迹图。 points.txt 0.500002, -0.199996, 0.299998 0.500545, -0.199855, 0.299338 0.501112, -0.199688, 0.298704 0.501701, -0.199497, 0.298…

二叉树、堆和堆排序(优先队列)

前言&#xff1a; 本章会讲解二叉树及其一些相关练习题&#xff0c;和堆是什么。 二叉树&#xff1a; 二叉树的一些概念&#xff1a; 一棵二叉树是有限节点的集合&#xff0c;该集合可能为空。二叉树的特点是每一个节点最多有两个子树&#xff0c;即二叉树不存在度大于2的节点…

ArcGIS学习(七)图片数据矢量化

ArcGIS学习(七)图片数据矢量化 通过上面几个任务的学习,大家应该已经掌握了ArcGIS的基础操作,并且学习了坐标系和地理数据库这两个非常重要且稍微难一些的专题。从这一任务开始,让我们进入到实战案例板块。 首先进入第一个案例一一图片数据矢量化。 我们在平时的工作学…

02.数据结构

一、链表 作用&#xff1a;用于写邻接表&#xff1b; 邻接表作用&#xff1a;用于存储图或树&#xff1b; 1、用数组模拟单链表 #include<iostream> using namespace std;const int N 100010;// head 表示头结点的下标 // e[i] 表示结点i的值 // ne[i] 表示结点i的ne…

Oracle11g安装配置详细教程

Oracle Database 11g是一款广泛使用的关系型数据库管理系统&#xff0c;它为企业级的应用提供了强大的数据管理功能。本文将详细介绍如何在Windows环境下安装和配置Oracle 11g。 准备工作 系统要求&#xff1a;确保你的系统满足安装Oracle 11g的最低要求。对于Oracle 11g Rele…

解决Typora导出HTML不显示图片

解决Typora导出HTML不显示图片 产生原因 Typora导出HTML不显示图片&#xff0c;可能时图片存放在我们的硬盘中。 我们可以将markdown中的图片转化为base64格式&#xff0c;嵌入到html中。 解决步骤 首先&#xff0c;下载 TyporaToBase64.jar 密码:45jq 其次&#xff0c;将…

【hcie-cloud】【26】华为云Stack主机安全防护

文章目录 前言主机安全概述主机安全概念主机安全风险与挑战 - 黑客入侵安全风险管理难安全合规审查严格 主机安全服务HSS详述企业主机安全服务介绍主机安全服务 - 实现原理&#xff08;主机安全&#xff09;主机安全服务 - 实现原理&#xff08;容器安全&#xff09;主机安全服…

java数据结构与算法刷题-----LeetCode18. 四数之和

java数据结构与算法刷题目录&#xff08;剑指Offer、LeetCode、ACM&#xff09;-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 解题思路 此题为三数之和的衍生题&#xff0c;代码完全一样&#xff0c;只…

第75讲Avatar头像FooterHome实现

Avatar头像实现 avatar&#xff1a; <template><el-dropdown><span class"el-dropdown-link"><el-avatar shape"square" :size"40" :src"squareUrl" /></span><template #dropdown><el-drop…