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.rhkb.cn/news/301669.html

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

相关文章

【测试面试题】14题常见APP测试面试题(参考答案)

大家好&#xff0c;这份面试题不难&#xff0c;都是一些基础题。 先上一个面试题汇总图&#xff0c;建议大家可以先思考下如果是自己能不能回答全&#xff0c;再去对照看参考答案。 下面为参考答案&#xff1a; 一、基础篇 1、APP的测试流程&#xff1f; APP测试流程与web测…

什么是并行通信、串行通信?什么是全双工、半双工、单工? 什么是异步通信、同步通信? 什么是RS232、RS485?什么是pwm?

这篇文章主要讲一下单片机中的通信相关的内容 主要讲一下以下5个问题&#xff1a; 1.什么是并行通信、串行通信&#xff1f; 2.什么是全双工、半双工、单工&#xff1f; 3.什么是异步通信、同步通信&#xff1f; 4.什么是RS232、RS485&#xff1f; 5.什么是pwm&#xff1f;什…

初识CSS

目录 前言&#xff1a; CSS的介绍&#xff1a; CSS的发展&#xff1a; 1&#xff09;CSS1.0&#xff1a; 2)CSS2.0: 3)CSS2.1: 4&#xff09;CSS3&#xff1a; CSS特点&#xff1a; 1&#xff09;丰富的样式定义&#xff1a; 2&#xff09;易于设置和修改&#xff1a; 3&…

网络电视盒子哪个品牌好?2024畅销电视盒子排行榜

电视盒子的品牌和产品非常多&#xff0c;让新手在选购时难度增大&#xff0c;大部分消费者在此时会选择参考销量排名情况&#xff0c;小编这次结合各个电商平台的销量和用户评价整理了电视盒子排行榜&#xff0c;想买电视盒子不知道网络电视盒子哪个品牌好可以收藏。 TOP 1.泰捷…

前端开发之Element树结构组件el-input的type=“password“时候账号密码自动填充解决方案

Element树结构组件el-input的type“password“时候账号密码自动填充解决方案 前言效果图解决方案 前言 在使用element的input的password当参数和login的参数相同时&#xff0c;在浏览器保存的用户名密码会自动填充&#xff0c;导致input附加上默认值 使用场景一般是在用户管理…

K8s学习八(配置与存储_配置)

配置与存储 配置管理 ConfigMap ConfigMap的创建 一般用于去存储 Pod 中应用所需的一些配置信息&#xff0c;或者环境变量&#xff0c;将配置于 Pod 分开&#xff0c;避免应为修改配置导致还需要重新构建 镜像与容器。configmap缩写为cmkubectl create cm -h来查看创建命令…

物联网实战--驱动篇之(四)LoRa应用(modbus)

目录 一、前言 二、板级收发 三、主机请求 四、从机接收及回复 五、主机接收 一、前言 之前两篇分别介绍了modbus和sx1278的驱动&#xff0c;但是都并未具体讲解如何应用&#xff0c;那么这一篇就把两者结合起来&#xff0c;做个小demo&#xff0c;便于理解这两个驱动的使…

测试开发面经(Flask,轻量级Web框架)

1. Flask的核心特点 a. 轻量级&#xff1a;核心简洁&#xff0c;只提供了基本的功能&#xff0c;其他高级功能可以通过插件或扩展来添加。 b. 灵活性&#xff1a;允许开发者选择适合自己项目的组件和工具&#xff0c;没有强制的项目结构和设计模式。 c. 易于扩展&#xff1a;提…

蓝桥杯刷题-09-三国游戏-贪心⭐⭐⭐

蓝桥杯2023年第十四届省赛真题-三国游戏 小蓝正在玩一款游戏。游戏中魏蜀吴三个国家各自拥有一定数量的士兵X, Y, Z (一开始可以认为都为 0 )。游戏有 n 个可能会发生的事件&#xff0c;每个事件之间相互独立且最多只会发生一次&#xff0c;当第 i 个事件发生时会分别让 X, Y,…

并发 ---- 多线程原理及底层实现

并发现象遍布日常生活&#xff0c;我们时常接触&#xff1a;我们可以边走路边说话&#xff1b;或者&#xff0c;左右手同时做出不一样的动作。在计算机应用程序中也有很好的例子&#xff1a; 浏览器 - 浏览器可以同时下载任意数量的文件和打开多个网页&#xff0c;下载时仍允许…

【Linux】进程控制之进程程序替换

目录 前言 替换的原理 替换函数 记忆技巧 函数使用 execl execlp execv execvp execle execvpe 调用其它语言的程序 模拟实现一个shell 前言 关于本文可以先去看看上一篇【Linux】进程控制详解-CSDN博客可以更好的理解这里的内容 学完本篇文章&#xff0c;你就…

AI智能分析盒子在工地的应用,提高工地管理效率和安全性

工地ai智能分析盒子是一种基于人工智能视觉分析技术的人工智能盒子&#xff0c;旨在提升工地作业区域的管理效率和保障作业人员的安全。通过最前沿的AI视觉算法、大数据&#xff0c;能够实时监控工地现场视频流画面&#xff0c;对施工工地人员的工作着装及日常作业行为进行规范…

OpenCV 4.9基本绘图

返回&#xff1a;OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇&#xff1a;OpenCV使用通用内部函数对代码进行矢量化 下一篇:使用OpenCV4.9的随机生成器和文本 ​目标 在本教程中&#xff0c;您将学习如何&#xff1a; 使用 OpenCV 函数 line() 画一…

产品经理和项目经理的区别

1. 前言 本文深入探讨了产品经理与项目经理在职责、关注点以及所需技能方面的显著区别。产品经理主要负责产品的规划、设计和市场定位,强调对用户需求的深刻理解和产品创新的推动;而项目经理则侧重于项目的执行、进度控制和资源管理,确保项目按时、按质、按预算完成。两者在…

一文搞懂从爬楼梯到最小花费(力扣70,746)

文章目录 题目前知动态规划简介动态规划模版 爬楼梯一、思路二、解题方法三、Code 使用最小花费爬楼梯一、思路二、解题方法三、Code 总结 在计算机科学中&#xff0c;动态规划是一种强大的算法范例&#xff0c;用于解决多种优化问题。本文将介绍动态规划的核心思想&#xff0c…

CTK插件框架学习-服务工厂(06)

CTK插件框架学习-信号槽(05)https://mp.csdn.net/mp_blog/creation/editor/137240105 一、服务工厂定义 注册插件时使用服务工厂注册&#xff0c;使用getService根据调用者插件资源文件内容获取在服务工厂内的对应实现在服务工厂中可以知道是哪个插件正在调用服务工厂懒汉模式…

rabbitmq死信交换机,死信队列使用

背景 对于核心业务需要保证消息必须正常消费&#xff0c;就必须考虑消费失败的场景&#xff0c;rabbitmq提供了以下三种消费失败处理机制 直接reject&#xff0c;丢弃消息&#xff08;默认&#xff09;返回nack&#xff0c;消息重新入队列将失败消息投递到指定的交换机 对于核…

代码随想录第34天| 1005.K次取反后最大化的数组和 134. 加油站 135. 分发糖果

1005.K次取反后最大化的数组和 1005. K 次取反后最大化的数组和 - 力扣&#xff08;LeetCode&#xff09; 代码随想录 (programmercarl.com) 贪心算法&#xff0c;这不就是常识&#xff1f;还能叫贪心&#xff1f;LeetCode&#xff1a;1005.K次取反后最大化的数组和_哔哩哔…

10.枚举

1.背景及定义 枚举是在JDK1.5以后引入的。 主要用途是&#xff1a; 将一组常量组织起来&#xff0c; 在这之前表示一组常量通常使用定义常量的方式&#xff1a; public static final int RED 1; public static final int GREEN 2; public static final int BLACK 3; 但是…

Web Component 组件库有什么优势

前言 前端目前比较主流的框架有 react&#xff0c;vuejs&#xff0c;angular 等。 我们通常去搭建组件库的时候都是基于某一种框架去搭建&#xff0c;比如 ant-design 是基于 react 搭建的UI组件库&#xff0c;而 element-plus 则是基于 vuejs 搭建的组件库。 可能你有这种体…