Leetcode刷题-哈希表详细总结(Java)

哈希表

当我们想使⽤哈希法来解决问题的时候,我们⼀般会选择如下三种数据结构。

  • 数组
  • set (集合)
  • map(映射)

当我们遇到了要快速判断⼀个元素是否出现集合⾥的时候,就要考虑哈希法。如果在做⾯试题⽬的时候遇到需要判断⼀个元素是否出现过的场景也应该第⼀时间想到哈希法!

这一部分的题就是需要注意,如果用到了set,map,在定义的时候需要用包装类,也就是引用数据类型,而不是基本数据类型

0、泛型不能直接使用基本数据类型!!!

例如 intdoublechar 等。但是 Java 提供了对应的包装类来解决这个问题,例如 IntegerDoubleCharacter 等。所以,你可以在泛型中使用这些包装类来代替基本数据类型。

​ 例如,你可以使用 Integer 代替 intDouble 代替 doubleCharacter 代替 char,以及其他包装类来替代其他基本数据类型。

// byte 对应 Byte
// short 对应 Short
// int 对应 Integer
// long 对应 Long
// float 对应 Float
// double 对应 Double
// char 对应 Character
// boolean 对应 Boolean

1、有效的字⺟异位词(数组哈希表)

242. 有效的字母异位词 - 力扣(LeetCode)

其实就是不能出现一个字母只在前面出现,但是没在后面那个字符串中。并且需要 st 中每个字符出现的次数都相同

在这里插入图片描述

可以用数组,遍历字符串,然后设一个数组,hash[26],每遍历到一个字母,相应位置加1,之后遍历第二个字符串,遍历到对应字母就去减1,然后看最后这个hash中有无负值

public boolean isAnagram(String s, String t) {int[] hash = new int[26];for(int i = 0; i < s.length(); i++){hash[s.charAt(i) - 'a']++;   // 并不需要记住字符a的ASCII,只要求出⼀个相对数值就可以了}for(int i = 0; i < t.length(); i++){hash[t.charAt(i) - 'a']--;}for(int i = 0; i < 26; i++){if(hash[i] != 0)return false;}return true;
}

2、两个数组的交集(set)

349. 两个数组的交集 - 力扣(LeetCode)

在这里插入图片描述

一个set集合用于存放第一个数组中的元素,另外一个用于在遍历第二个数组的时候,去查找如果有相同元素情况,就存放进去

之后结果数组的大小,就是基于第二个set集合的大小new出来的。并且遍历第二个set集合,将里面的元素放进最终数组里。

public int[] intersection(int[] nums1, int[] nums2) {HashSet<Integer> set = new HashSet<Integer>();HashSet<Integer> result = new HashSet<Integer>();for(int i = 0; i < nums1.length; i++){set.add(nums1[i]);}for(int i = 0; i < nums2.length; i++){if(set.contains(nums2[i]))result.add(nums2[i]);}int[] res = new int[result.size()];int n = 0;for(int num: result){res[n++] = num;}return res;
}

3、两数之和(HashMap)

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

在这里插入图片描述

这道题需要明确借助map的话,key和value分别存放什么

因为我们是需要基于数组值去查询的,所以key存放的是数组值,value存放的是对应的索引

在遍历数组的时候,只需要向map去查询是否有和⽬前遍历元素匹配的数值,如果有,就找到的匹配对,如果没 有,就把⽬前遍历的元素放进map中,因为map存放的就是我们访问过的元素。

public int[] twoSum(int[] nums, int target) {HashMap<Integer,Integer> map = new HashMap<Integer,Integer>();  int[] result = new int[2];map.put(nums[0],0);for(int i = 1; i < nums.length; i++){if(map.containsKey(target - nums[i])){result[0] = map.get(target - nums[i]);result[1] = i;return result;}map.put(nums[i],i);}return result;
}

4、四数相加

454. 四数相加 II - 力扣(LeetCode)

在这里插入图片描述

这题和四数之和的区别在于,这是四个数组,所以不需要考虑去重,因为四个数组是独立的,而四数之和问题是针对于一个数组。会可能结果出现重复的

本题的思路

将四个数组两两划分到一组

  1. 遍历⼤A和⼤B数组,统计两个数组元素之和(key),和出现的次数(value),放到map中。
  2. 定义int变量count,⽤来统计 a+b+c+d = 0 出现的次数。
  3. 在遍历⼤C和⼤D数组,找到如果 0-(c+d) 在map中出现过的话,就⽤count把map中key对应的value也就是出现次数统计出来。注意value是多少,那说明就出现过几次四数之和是这个目标target值的情况
  4. 最后返回统计值 count 就可以了
public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {HashMap<Integer,Integer> map = new HashMap<Integer, Integer>();int count = 0;int n;for(int i = 0; i < nums1.length; i++){for(int j = 0; j < nums2.length; j++){if(map.get(nums1[i] + nums2[j]) == null)n = 1;elsen = map.get(nums1[i] + nums2[j])+1;map.put(nums1[i] + nums2[j],n++);}}for(int i = 0; i < nums3.length; i++){for(int j = 0; j < nums4.length; j++){int tmp = 0 - nums3[i] - nums4[j];if(map.containsKey(tmp))count += map.get(tmp);}}return count;
}
  • 这个题在写代码时候,需要注意,在填充次数的时候,由于Integer不存在0的情况,只是null

  • 这是和int基本数据类型的一大区别,所以我们需要判断他是不是本身不存在,然后赋值

5、三数之和

15. 三数之和 - 力扣(LeetCode)

在这里插入图片描述

首先想到哈希解决,可以用两个for循环,然后判断出来是不是存在一个key = 【0-a-b】

但是这个就有一个问题,会有重复的三元组,需要去重

因此,这里选择用另外一种方法:双指针法,会更高效一点

  • 由于我们需要返回值,不用返回下标,所以可以提前对数组进行排序

  • 之所以排序,因为我们的思路是让 i 去遍历数组,然后left首先指向【i+1】的位置,right指向最后一个位置

  • 如果nums[ i ] + nums[ left ] + nums[ right ] > 0;这时候如果排过序,可以让right–。就类似这样的操作。并且如果nums[ i ]本身就是大于0的,那就可以不用找了,因为left 和 right只会更大

  • 也需要进行去重

    1. 需要判断nums[ i ] == nums[ i - 1 ],因为如果之前一个元素和当前位置元素相同,那他获取到的结果,会和我们此次获取到的结果有重复情况,注意必须是判断当前元素和前一个元素,而不是和后一个元素nums[ i + 1 ]相比
    2. 在收获了一个三元组之后需要对于left指针部分去重:在left++之前,如果nums[ left ] ==nums[ left+1 ],就持续left++【用while判断】
    3. 在收获了一个三元组之后需要对于left指针部分去重:在right–之前,nums[ right ] == nums[ right-1 ],就持续right–【用while判断】

在这里插入图片描述

public List<List<Integer>> threeSum(int[] nums) {int n = nums.length;Arrays.sort(nums);List<List<Integer>> result = new ArrayList<List<Integer>>();// 找出a + b + c = 0// a = nums[i], b = nums[left], c = nums[right]for(int i = 0; i < n; i++){if(nums[i] > 0)  // 排序后如果第一个元素已经大于零,无论如何组合都不可能凑成三元组,直接返回结果就可以了return result;if(i > 0 && nums[i] == nums[i-1]) // 去重acontinue;int left = i + 1;int right = n - 1;while(left < right){if(nums[i] + nums[left] + nums[right] > 0)right--;else if(nums[i] + nums[left] + nums[right] < 0)left++;else{List<Integer> list = new ArrayList<Integer>();list.add(nums[i]);list.add(nums[left]);list.add(nums[right]);result.add(list);// 去重逻辑应该放在找到一个三元组之后,对b 和 c去重  一定要用while不是用if!!!!!!!while (right > left && nums[right] == nums[right - 1]) right--;while (right > left && nums[left] == nums[left + 1]) left++;right--;   //别忘了上面只是判断,这里才是真正的移动!!!!!!left++;}}}return result;
}

6、四数之和

18. 四数之和 - 力扣(LeetCode)

和三数之和一样,都是在一个数组上寻找四个元素的和等于target值,并且要求结果里面不能有重复的四元组结合

基本思路:

在三数之和的思路上,外面再加上一层for循环

这里的剪枝和对nums[ k ]的去重稍微有点不一样,因为这次是和target手动输入的值作比较,不像三数之和是单纯的和零做比较

public List<List<Integer>> fourSum(int[] nums, int target) {List<List<Integer>> result = new ArrayList<>();Arrays.sort(nums);  for (int k = 0; k < nums.length; k++) {// nums[i] > target 直接返回, 剪枝操作if (nums[k] > 0 && nums[k] > target) {return result;}if (k > 0 && nums[k - 1] == nums[k]) {    // 对nums[i]去重continue;}for (int i = k + 1; i < nums.length; i++) {if (i > k + 1 && nums[i - 1] == nums[i]) {  // 对nums[j]去重continue;}int left = i + 1;int right = nums.length - 1;while (right > left) {// nums[k] + nums[i] + nums[left] + nums[right] > target int会溢出long sum = (long) nums[i] + nums[k] + nums[left] + nums[right];if (sum > target) {right--;} else if (sum < target) {left++;} else {result.add(Arrays.asList(nums[i], nums[k], nums[left], nums[right]));// 对nums[left]和nums[right]去重while (right > left && nums[right] == nums[right - 1]) right--;while (right > left && nums[left] == nums[left + 1]) left++;left++;right--;}}}}return result;
}

基于代码随想录的学习,同时刷题总结哈希表的常用思路以及一些刷题笔记

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

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

相关文章

Samba 总是需要输入网络凭证

输入网络凭证&#xff1a; 用户名是 cat /etc/samba/smb.conf&#xff0c;查看 valid users mxw 为用户名。而不是其他账号名或者用户名&#xff0c;更不是登录计算机时的计算机名&#xff1b; 密码是 需要记住安装samba服务器时&#xff0c;自己设置的password&#xff1…

LED发光模组的故障及解决方法

LED发光模组在应用过程中可能会出现各种故障&#xff0c;正确诊断并采取相应的解决方法至关重要&#xff0c;以下是一些常见故障现象及其解决方法的总结&#xff1a; 一、现象&#xff1a;所有的LED闪烁 问题&#xff1a;接触不良 解决方法&#xff1a;检查并重新固定松动处&am…

单片机为什么还在用C语言编程?

单片机产品的成本是非常敏感的。因此对于单片机开发来说&#xff0c;最重要的是在极其有限的ROM和RAM中实现最多产品的功能。或者反过来说&#xff0c;实现相同的产品功能&#xff0c;所需要的ROM和RAM越小越好&#xff0c;在开始前我有一些资料&#xff0c;是我根据网友给的问…

linux网络预备

网络预备 网络协议初识 协议分层 打电话例子 在这个例子中, 我们的协议只有两层; 但是实际的网络通信会更加复杂, 需要分更多的层次。 分层最大的好处在于 “封装” 。 OSI七层模型 OSI&#xff08;Open System Interconnection&#xff0c;开放系统互连&#xff09;七层网…

Datacom HCIP笔记-路由策略与路由控制 之二

路由策略和策略的区别&#xff1f; 路由策略&#xff1a; 操作的对象是路由表条目&#xff0c; 实现路由过滤&#xff0c;从而实现访问控制&#xff0c;引入时过滤&#xff0c;发送和接收路由时过滤。 通过配置cost&#xff0c;来实现路径的控制。 策略路由&#xff1a; 对…

【Vue3源码学习】— CH2.8 Vue 3 响应式系统小结

Vue 3 响应式系统小结 1.核心概念1.1 Proxy和Reflect1.2 响应式API1.3 依赖收集与更新触发1.4 触发更新&#xff08;Triggering Updates&#xff09;&#xff1a;1.5 副作用函数&#xff08;Effect&#xff09;1.6 计算属性和观察者1.7 EffectScope1.8 性能优化&#xff1a; 2.…

GPT-5将在6月发布前进行「红队进攻测试」

“GPT-5将在6月发布”的消息刷屏了AI朋友圈。这则消息之所以被无数人相信并转发&#xff0c;是因为已经有不少技术人员在社交平台上晒出了「红队进攻测试」邀请。 基于 GPT系列庞大的用户体量和影响力&#xff0c;OpenAI 将更加重视GPT-5 的安全性&#xff0c;作为GPT-5上市前的…

【编译原理】手工打造语法分析器

重点&#xff1a; 语法分析的原理递归下降算法&#xff08;Recursive Descent Parsing&#xff09;上下文无关文法&#xff08;Context-free Grammar&#xff0c;CFG&#xff09; 关键点&#xff1a; 左递归问题深度遍历求值 - 后续遍历 上一篇「词法分析器」将字符串拆分为…

水经微图网页版309项功能清单

让每一个人都有自己的地图&#xff01; 水经微图&#xff08;简称“微图”&#xff09;网页版&#xff0c;是越来越受到大家的亲睐了&#xff01; 就后台统计数据来看&#xff0c;日均IP数据在稳步增长&#xff0c;老访客的占比最高达35%以上。 在上上周&#xff0c;还分别有…

PMP考试费太贵,能不能自学?

最近6月PMP考试报名工作正在如火如荼的进行&#xff0c;可能大家对于考试费用已经有了基本了解&#xff0c;今天给大家分享一下PMP证书考下来需要花费多少&#xff1f;能不能自己学习&#xff1f; PMP是什么&#xff1f; PMP项目管理专业人士资格认证&#xff0c;由项目管理协…

uniapp - 微信小程序 - 使用uCharts的一些问题

文章目录 uniapp - 微信小程序 - 使用uCharts的一些问题一、开发者工具显示正常&#xff0c;真机调试统计图不随页面滚动二、数据过多开启滚动条&#xff0c;无法滑动滚动条三、饼图点击不显示提示窗/点击位置bug、多个同类型统计图点击不显示提示框问题四、 formatter 自定义 …

ArcGIS Pro怎么进行挖填方计算

在工程实施之前&#xff0c;我们需要充分利用地形&#xff0c;结合实际因素&#xff0c;通过挖填方计算项目的标高&#xff0c;以达到合理控制成本的目的&#xff0c;这里为大家介绍一下ArcGIS Pro中挖填方计算的方法&#xff0c;希望能对你有所帮助。 数据来源 教程所使用的…

Python—循环加强

1.使用循环打印等腰三角形 # 画三角形层数为n # 第i层有空格&#xff1a;n-i # 第i层有*&#xff1a;2*i-1 n int(input("层数&#xff1a;"))#层数n for i in range(1, n 1):#范围在1~n# 画空格for _ in range(1, n - i 1): # _不用显示&#xff0c;用于表示&a…

MySQL一条SQL语句的执行过程

MySQL一条SQL语句的执行过程可以大致分为以下几个步骤&#xff1a; mysq分层架构 为了理解这个问题&#xff0c;先从Mysql的架构说起&#xff0c;对于Mysql来说&#xff0c;大致可以分为3层架构。 网络连接层&#xff1a; 作为客户端和服务端的连接&#xff0c;连接器负责处…

Leetcode 17.电话号码的字母组合

题目 思路 输入的digits有几个数就有几层。 一层中有几个数则取决于输入的数字对应的字母有几个。 1.确定递归函数的返回值及参数&#xff1a; 其实参数不是一开始就确定好的&#xff0c;而是你在写递归函数的时候缺啥&#xff0c;就往进去传啥。 这里我就直接全部写出来。…

无线基本认识和配置

1、无线局域网 IEEE 802.11标准 根据应用范围分类 WPAN --- 个人无线网络 NFC、ZIgbee、Bluetooth WLAN --- 无线局域网 WiFi&#xff0c;使用到WPAN技术 WMAN --- 无线城域网 WiMax 802.16 WWAN --- 无线广域网 GSM、CDMA、WCDMA、LTE、5G、TD-SCDMA 2、…

2012年认证杯SPSSPRO杯数学建模C题(第一阶段)碎片化趋势下的奥运会商业模式全过程文档及程序

2012年认证杯SPSSPRO杯数学建模 C题 碎片化趋势下的奥运会商业模式 原题再现&#xff1a; 从 1984 年的美国洛杉矶奥运会开始&#xff0c;奥运会就不在成为一个“非卖品”&#xff0c;它在向观众诠释更高更快更强的体育精神的同时&#xff0c;也在攫取着巨大的商业价值&#…

关东升老师力作!四本编程宝典,带你畅游编程世界

&#x1f31f;《看漫画学C》&#xff1a;关东升老师以漫画的形式&#xff0c;让你在欢笑中轻松掌握C编程的核心知识。不再枯燥&#xff0c;不再难懂&#xff0c;让编程变得有趣又简单&#xff01; &#x1f3a8;《MATLAB科研绘图与学术图表绘制从入门到精通》&#xff1a;关东升…

c++的学习之路:15、list(2)

本章主要是讲模拟实现list&#xff0c;文章末附上代码。 目录 一、创建思路 二、构造函数 三、迭代器 四、增删 五、代码 一、创建思路 如下方代码&#xff0c;链表是由一块一块不连续的空间组成的&#xff0c;所以这里写了三个模板&#xff0c;一个是节点&#xff0c;一…

蓝桥杯第六届c++大学B组详解

前言&#xff1a; 看了很多博客以及视频讲解&#xff0c;感觉都不是很清楚&#xff0c;比较模棱两可&#xff0c;所以干脆自己一边想&#xff0c;一边写博客&#xff0c;也可帮助到其他人&#xff0c;都是根据自己的逻辑来尽量清楚简单的讲清楚题目&#xff0c;喜欢的不要吝啬三…