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

news2024/11/15 13:37:14

哈希表

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

  • 数组
  • 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;
            else
                n = 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]) // 去重a
            continue;
        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.coloradmin.cn/o/1575379.html

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

相关文章

搭建好WordPress网站后的基本操作流程

考虑到很多朋友是第一次使用WordPress&#xff0c;这里给大家分享一下基本的WordPress操作流程&#xff0c;你可以跟着实际情况决定操作步骤。 1.设置网站SSL安全证书。 我采用的是Hostease家的Linux主机产品&#xff0c;自带免费SSL证书 。支持一键安装wordpress程序。 2.进…

智慧驿站式的“智慧公厕”,给城市新基建带来新变化

随着智慧城市建设的推进&#xff0c;智慧驿站作为一种多功能城市部件&#xff0c;正逐渐在城市中崭露头角。这些智慧驿站集合了智慧公厕的管理功能&#xff0c;为城市的新基建带来了全新的变革。本文以智慧驿站智慧公厕源头实力厂家广州中期科技有限公司&#xff0c;大量精品案…

MyBatis操作数据库(1)

前言 在应用分层的学习时, 我们了解到web应用程序一般分为三层,即Controller, Service, Dao. 之前的案例中, 请求流程如下: 浏览器发起请求, 先请求Controller, Controller接受到请求后,调用Service进行业务逻辑处理, Service再调用Dao, 但是Dao层的数据是Mock的, 真实的数据…

基于 Vue3 + Webpack5 + Element Plus Table 二次构建表格组件

基于 Vue3 Webpack5 Element Plus Table 二次构建表格组件 文章目录 基于 Vue3 Webpack5 Element Plus Table 二次构建表格组件一、组件特点二、安装三、快速启动四、单元格渲染配置说明五、源码下载地址 基于 Vue3 Webpack5 Element Plus Table 二次构建表格组件&#x…

【白菜基础】蛋白组学之生信分析(1)

刚换了一个新课题组&#xff0c;新老板的研究方向为蛋白组学&#xff0c;从未接触过蛋白组学的我准备找一组模拟数据进行生信分析的入门学习。 蛋白组学数据挖掘流程图&#xff0c;参考公众号&#xff1a;蛋白质组学数据挖掘思路解析 (qq.com) 一、认识数据 我们组的数据主要…

【高校科研前沿】中国科学院南京地理与湖泊研究所肖启涛博士为一作在Sci. Bull发文:我国湖泊二氧化碳从大气的源向汇转变

目录 1.文章简介 2.研究内容 3.文章引用 1.文章简介 论文名称&#xff1a;Lakes shifted from a carbon dioxide source to a sink over past two decades in China 第一作者及通讯作者&#xff1a;肖启涛&#xff08;博士生&#xff09;&#xff0c;段洪涛&#xff08;研究…

【已解决】HalconDotNet.HOperatorException:“HALCON error #1201: Wrong type of control

前言 最近在学习Halcon视觉和C#的联合开发&#xff0c;碰到一个比较有意思的问题记录一下&#xff0c;大致的报错信息是说我用的halcondotnet版本和我在halcon导出的使用的halcondotnet.dll版本不一致&#xff0c;所以才报错的&#xff01; 解决 首先你得找到你安装halcon的…

接口自动化入门:Jmeter的多组数据测试、JDBC驱动及数据断言!

在进行接口测试时&#xff0c;我们经常需要对接口进行多组数据测试&#xff0c;以验证接口在不同输入条件下的表现。同时&#xff0c;我们也需要对接口返回的数据进行断言&#xff0c;以确保接口返回的数据符合预期结果。JMeter正是一个强大的工具&#xff0c;可以帮助我们实现…

【Linux】正则表达式实验操作实例

正则表达式是一种强大的工具&#xff0c;用于在文本中查找、匹配和替换特定的字符串模式。 实验目的 掌握正则表达式的表达方式掌握grep/egrep命令的用法掌握sed 命令的用法掌握awk命令的用法 正则表达式 实验目的实验内容实验过程创建grep文件来进行如下操作用sed命令完成下列…

寻找排序数组中的最小值

题目描述 已知一个长度为 n 的数组&#xff0c;预先按照升序排列&#xff0c;经由 1 到 n 次 旋转 后&#xff0c;得到输入数组。例如&#xff0c;原数组 nums [0,1,2,4,5,6,7] 在变化后可能得到&#xff1a; 若旋转 4 次&#xff0c;则可以得到 [4,5,6,7,0,1,2]若旋转 7 次…

如何水出第一篇SCI:SCI发刊历程,从0到1全过程经验分享!!!

如何水出第一篇SCI&#xff1a;SCI发刊历程&#xff0c;从0到1全路程经验分享&#xff01;&#xff01;&#xff01; 详细的改进教程以及源码&#xff0c;戳这&#xff01;戳这&#xff01;&#xff01;戳这&#xff01;&#xff01;&#xff01;B站&#xff1a;Ai学术叫叫兽e…

机器学习(30)

文章目录 摘要一、文献阅读1. 题目2. abstract3. 网络架构3.1 Sequence Generative Adversarial Nets3.2 SeqGAN via Policy Gradient3.3 The Generative Model for Sequences3.4 The Discriminative Model for Sequences(CNN) 4. 文献解读4.1 Introduction4.2 创新点4.3 实验过…

UWB 雷达动目标检测

1. 静态载波滤除 1. 首先对所有接收脉冲求平均得出参考接收脉冲 [Cir数据为二维数组64*n&#xff0c; 其中n为慢时间域采样的数据帧数] 2. 接着利用每一束接收脉冲减去参考接收脉冲就可以得到目标回波信号&#xff0c;参考接收脉冲的表达式为 2. RD 谱 对雷达回波做静态载波滤…

Linux:IO多路转接之epoll

文章目录 epoll历史epoll的接口epoll_createepoll_waitepoll_ctl epoll原理代码实验 前面的内容介绍了select多路转接&#xff0c;也分析了其利弊&#xff0c;后面用poll改良了select&#xff0c;解决了部分的缺点&#xff0c;但是对于一些核心的缺点还是不能保证&#xff0c;比…

Langchain教程 | langchain+OpenAI+PostgreSQL(PGVector) 实现全链路教程,简单易懂入门

前提&#xff1a; 在阅读本文前&#xff0c;建议要有一定的langchain基础&#xff0c;以及langchain中document loader和text spliter有相关的认知&#xff0c;不然会比较难理解文本内容。 如果是没有任何基础的同学建议看下这个专栏&#xff1a;人工智能 | 大模型 | 实战与教程…

品牌定位升级|飞雕开关如何从家庭作坊走上国际之路?

飞雕电器,这个名字在中国开关插座行业中如同一面旗帜,自1987年起就扬帆在电工领域的大海中。它不仅见证了这个行业的起起伏伏,还始终以其创新的姿态站在浪尖之上。 飞雕的产品线丰富多彩,除主营的墙壁开关插座领域外,飞雕电器还涉足了与墙壁开关紧密相关的其它领域,现已推出移…

vmware 中的Ubuntu系统虚拟机忘记root密码强制重置操作

忘记密码情况下&#xff0c;vmware虚拟机重置Ubuntu的root密码 在企业使用的vmware ESXI中重置Ubuntu系统root密码 1-本地电脑安装个人版的vmware workstation&#xff0c;目的&#xff1a;vmware ESXI自带的远程控制台无法输入指定的键盘按键&#xff0c;需要借助外部的远程辅…

Ceph学习 -3.存储简介

文章目录 1.存储简介1.1 存储类型1.1.1 储备知识1.1.2 三种存储1.1.3 块存储1.1.4 文件存储1.1.5 对象存储1.1.6 三种存储之间的关系1.1.7 总结 1.2 Ceph简介1.2.1 官方介绍1.2.2 软件特点1.2.3 基本结构1.2.4 应用场景 1.3 小结 1.存储简介 学习目标&#xff1a;这一节&#x…

免疫检查点信号转导和癌症免疫治疗(文献)

目录 基础 介绍 免疫检查点的表面调控&#xff08;细胞膜层面&#xff09; ​编辑 PD-1调节 PD-L1调节 CTLA-4 调节 检查点信号通路 关于靶点研究 展望 Immune checkpoint signaling and cancer immunotherapy - PubMed (nih.gov) 基础 【中英字幕】肿瘤免疫疗法之免…

docker安装nacos,单例模式(standalone),使用mysql数据库

文章目录 前言安装创建文件夹"假装"安装一下nacos拷贝文件夹删除“假装”安装的nacos容器生成nacos所需的mysql表获取mysql-schema.sql文件创建一个mysql的schema 重新生成新的nacos容器 制作docker-compose.yaml文件查看网站 前言 此处有本人写得简易版本安装&…