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;
            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;
}

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Frida】【Android】 10_爬虫之WebSocket协议分析

&#x1f6eb; 系列文章导航 【Frida】【Android】01_手把手教你环境搭建 https://blog.csdn.net/kinghzking/article/details/136986950【Frida】【Android】02_JAVA层HOOK https://blog.csdn.net/kinghzking/article/details/137008446【Frida】【Android】03_RPC https://bl…

鸿蒙HarmonyOS 与 Android 的NDK有什么不一样?

1. 序言 就像开发Android要用Android Studio一样&#xff0c;Android Studio&#xff08;简称AS&#xff09;其实是基于IDEAgradle插件android插件开发而来。 鸿蒙系统&#xff0c;你可以认为它和android有点像&#xff0c;但又是超越android的存在&#xff0c;除了手机&…

IO流

一、IO概述 1&#xff0e;什么是IO流? 存储和读取数据的解决方案l: inputo: output流∶像水流一样传输数据 2.IO流的作用? 用于读写数据&#xff08;本地文件&#xff0c;网络) 3.IO流按照流向可以分类哪两种流? 输出流:程序 - > 文件 输入流:文件 - > 程…

30道python自动化测试面试题与答案汇总!

Python是不可或缺的语言,它的优美与简洁令人无法自拔,下面这篇文章主要给大家介绍了关于30道python自动化测试面试题与答案汇总的相关资料,需要的朋友可以参考下 1、什么项目适合做自动化测试&#xff1f; 关键字&#xff1a;不变的、重复的、规范的 1&#xff09;任务测试明…

Collection与数据结构 Stack与Queue(二):队列与Queue

1. 队列 1.1 概念 只允许在一端进行插入数据操作&#xff0c;在另一端进行删除数据操作的特殊线性表&#xff0c;队列具有先进先出FIFO(First In First Out) 入队列&#xff1a;进行插入操作的一端称为队尾&#xff08;Tail/Rear&#xff09; 出队列&#xff1a;进行删除操作…

JVM内存性能调优思路之:通过GC log、Thread Dump 、Heap Dump分析内存使用说明

文章目录 一. 各日志概述1. Garbage Collection Log - 找到GC规律2. 线程转储(Thread dump) - 分析&#xff08;快照&#xff09;线程状态3. 堆转储(Heap dump) - APP某刻内存使用全貌 二. 命令1. 程序的gc日志2. 线程转储3. 堆转储 概述 在 Java 虚拟机中&#xff0c;(GC) Gar…

C语言分支语句

一、什么是语句 C语句可分为以下五类&#xff1a; 表达式语句 函数调用语句 控制语句 复合语句 空语句 本周后面介绍的是控制语句。 控制语句用于控制程序的执行流程&#xff0c;以实现程序的各种结构方式&#xff0c;它们由特定的语句定义符组成&#xff0c;C语 言有…

测试工程师求职是选自研公司还是选外包公司呢?

大家好&#xff0c; 今天我们一起来聊一聊测试工程师求职是选自研公司&还是选外包公司呢&#xff1f; 今天来谈谈我的个人看法&#xff0c;作为一个在测试岗位上多年的我来说&#xff0c;自研公司比较好&#xff0c;外包公司其实也不会差。各自都有特点特色&#xff0c;根据…

虚拟主机VPS和共享服务器有什么区别?VPS和共享服务器怎么选择,VPS和云服务器区别

今天易极赞小编来跟大家科普一个新的知识“虚拟主机和云服务器有什么区别&#xff1f;”看完这篇文章后你应该就能知道虚拟主机和云服务器哪个更适合你了。 如果你不知道服务器的常见类型有哪些&#xff0c;查看下面这篇文章&#xff1a; 服务器7中常见的类型&#xff0c;服务…

刷力扣中学习使用static,final

. - 力扣&#xff08;LeetCode&#xff09;. - 备战技术面试&#xff1f;力扣提供海量技术面试资源&#xff0c;帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/throne-inheritance/今天在力扣题中第一次使用了static和final&#xf…

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…

Shiny Items VFX for URP

一系列令人惊叹且易于编辑的Shuriken粒子系统和粒子着色器&#xff0c;用于稀有物品、奖励或通电物品 用我的“闪亮物品”包提高你在URP项目中的稀有物品、奖项或电源的吸引力。 该包提供了使用Shuriken粒子系统创建的14个“项目”预制集&#xff0c;以及项目的自定义着色图着色…

PPP-B2b星历下载

目前做PPP-B2b研究比较多&#xff0c;其中PPP-B2b需要北斗的CNAV星历下载链接为&#xff08;例如2024.04.05对应的2024年第097天&#xff09;&#xff1a;数据下载http://www.csno-tarc.cn/datacenter/ephemeris

c++ Constraints 和 concepts介绍

C++20 引入了 Concepts,以改进模板编程的体验。Concepts 是一种用于模板编程的新机制,它允许程序员在编译时对模板参数进行约束和限制,从而提高模板的可读性、可维护性和错误检测能力。 Constraints(约束)是 Concepts 的一部分,它定义了模板参数必须满足的条件。一个约束…

《科技创业月刊》是什么级别的期刊?是正规期刊吗?能评职称吗?

问题解答&#xff1a;问&#xff1a;《科技创业月刊》是什么级别的刊物&#xff1f; 答&#xff1a;省级&#xff0c;主管单位&#xff1a; 湖北省科学技术厅 &#xff1b;主办单位&#xff1a;湖北省科技信息研究院 问&#xff1a;《科技创业月刊》是c刊吗&#xff1f; 答&…

Rustdesk二次编译,新集成AI功能开源Gpt小程序为远程协助助力,全网首发

环境&#xff1a; Rustdesk1.1.9 sciter版 问题描述&#xff1a; Rustdesk二次编译&#xff0c;新集成AI功能开源Gpt小程序为远程协助助力,全网首发 解决方案&#xff1a; Rustdesk二次编译&#xff0c;新集成开源AI功能Gpt小程序&#xff0c;为远程协助助力&#xff0c…

【C++】RapidJSON 设置支持 std::string,防止编译报错

问题 rapidjson 创建 json 数据&#xff0c;使用 std::string 字符串进行赋值&#xff0c;编译时&#xff0c;抱一堆错误 .... rapidjson/include/rapidjson/document.h:690:5: note: candidate expects 0 arguments, 1 provided [build] make[2]: *** [main/CMakeFiles/ma…

2024.4.7

1. 2列火车 #include<myhead.h>pthread_mutex_t m1; pthread_mutex_t m2;void* run(void* arg) {while(1){pthread_mutex_lock(&m1);printf("火车B进入\n");printf("A请等待\n");pthread_mutex_unlock(&m2);sleep(2);} }int main(in…

cookie、session、token的区别

这三者都和维持状态信息有关。比如我们如果在网页进行了一次登录&#xff0c;如果我们希望以后再访问该网页的时候&#xff0c;维持登录信息的话&#xff0c;就需要用到上面的这三种&#xff0c;如果不用的话&#xff0c;那么我们每次都需要携带登录信息到服务器&#xff0c;并…

海纳斯删除广告位

找到文件 vim /var/www/html/home.php 删除代码段 <div class"adleft" id"adleftContainer"><button onclick"closeAd()">关闭</button><a href"https://www.ecoo.top/ad.html" target"_blank">&l…