LeetCode_哈希表

哈希表(散列表)

  • 一、哈希表
  • 二、有效的字母异位词
    • 1、有效的字母异位词(力扣242)
    • 2、赎金信(力扣383)
    • 3、字母异位词分组(力扣49)
    • 4、找到字符串中所有字母异位词(力扣438)
  • 三、两个数组的交集
    • 1、两个数组的交集(力扣349)
    • 2、两个数组的交集 II(力扣350)
  • 三、其他的哈希表题
    • 1、快乐数(力扣202)
    • 2、两数之和(力扣1)
    • 3、四数相加 II(力扣454)
    • 4、三数之和(力扣15)
    • 5、四数之和(力扣18)

一、哈希表

1.总结一下,当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法。但是哈希法也是牺牲了空间换取了时间,因为我们要使用额外的数组,set或者是map来存放数据,才能实现快速的查找。如果在做面试题目的时候遇到需要判断一个元素是否出现过的场景也应该第一时间想到哈希法!
2.当数据量比较少时,可以考虑使用数组。直接使用set 不仅占用空间比数组大,而且速度要比数组慢,set把数值映射到key上都要做hash计算的。不要小瞧这个耗时,在数据量大的情况,差距是很明显的。

二、有效的字母异位词

1、有效的字母异位词(力扣242)

//1.t是s的异位词等价于「两个字符串排序后相等」public static boolean isAnagram(String s, String t) {if (s.length() != t.length()){return false;}char[] c1 = s.toCharArray();char[] c2 = t.toCharArray();Arrays.sort(c1);Arrays.sort(c2);return Arrays.equals(c1,c2);}
//2.输入字符串不包含 unicode 字符public static boolean isAnagram(String s, String t) {if (s.length() != t.length()){return false;}int[] arr = new int[26];for (int i = 0; i < s.length(); i++) {arr[s.charAt(i) - 'a'] ++;}for (int i = 0; i < t.length(); i++) {arr[t.charAt(i) - 'a'] --;if (arr[t.charAt(i) - 'a'] < 0){return false;}}return true;}

如果输入字符串包含 unicode 字符,那就只能使用哈希表了, JAVA的char类型是支持unicode的

//3.输入字符串包含 unicode 字符public static boolean isAnagram(String s, String t) {if (s.length() != t.length()){return false;}Map<Character,Integer> map = new HashMap<>();for (int i = 0; i < s.length(); i++) {map.put(s.charAt(i),map.getOrDefault(s.charAt(i),0) + 1);}for (int i = 0; i < t.length(); i++) {map.put(t.charAt(i),map.getOrDefault(t.charAt(i),0) - 1);if (map.get(t.charAt(i)) < 0){return false;}}return true;}

2、赎金信(力扣383)

//1.和242很像,没啥难度public static boolean canConstruct(String ransomNote, String magazine) {if (ransomNote.length() > magazine.length()){return false;}int[] arr = new int[26];for (int i = 0; i < magazine.length(); i++) {arr[magazine.charAt(i) - 'a'] ++;}for (int i = 0; i < ransomNote.length(); i++) {arr[ransomNote.charAt(i) - 'a'] --;if (arr[ransomNote.charAt(i) - 'a'] < 0){return false;}}return true;}
//2.哈希mappublic static boolean canConstruct(String ransomNote, String magazine) {if (ransomNote.length() > magazine.length()) {return false;}Map<Character, Integer> map = new HashMap<>();for (int i = 0; i < magazine.length(); i++) {map.put(magazine.charAt(i), map.getOrDefault(magazine.charAt(i), 0) + 1);}for (int i = 0; i < ransomNote.length(); i++) {map.put(ransomNote.charAt(i),map.getOrDefault(ransomNote.charAt(i),0) - 1);if (map.get(ransomNote.charAt(i)) < 0){return false;}}return true;}

3、字母异位词分组(力扣49)

//1.哈希mappublic List<List<String>> groupAnagrams(String[] strs) {//考虑清楚用什么来表示键和值Map<String,ArrayList<String>> map = new HashMap<>();for (String s : strs){char[] c = s.toCharArray();Arrays.sort(c);String key = String.valueOf(c);if (!map.containsKey(key)){map.put(key,new ArrayList<>());}map.get(key).add(s);}//map.values() 返回的是collection,直接是集合return new ArrayList<>(map.values());}

4、找到字符串中所有字母异位词(力扣438)

//1.自己想的public static List<Integer> findAnagrams(String s, String p) {if (s.length() < p.length()){return new ArrayList<>();}List<Integer> list = new ArrayList<>();char[] c1 = p.toCharArray();Arrays.sort(c1);for (int i = 0; i <= s.length() - p.length(); i++) {char[] c2 = s.substring(i,i + p.length()).toCharArray();Arrays.sort(c2);if (Arrays.equals(c1,c2)){list.add(i);}}return list;}
//2.滑动窗口public static List<Integer> findAnagrams(String s, String p) {int sLen = s.length(), pLen = p.length();if (sLen < pLen) {return new ArrayList<>();}//分别统计滑动窗口和p中的字符的数量int[] sCount = new int[26];int[] pCount = new int[26];List<Integer> list = new ArrayList<>();for (int i = 0; i < pLen; i++) {sCount[s.charAt(i) - 'a']++;pCount[p.charAt(i) - 'a']++;}if (Arrays.equals(sCount, pCount)) {list.add(0);}//滑动窗口向右移动,依次比较for (int i = 0; i < sLen - pLen; i++) {sCount[s.charAt(i) - 'a'] --;sCount[s.charAt(i + pLen) - 'a'] ++;if (Arrays.equals(sCount,pCount)){list.add(i + 1);}}return list;}

三、两个数组的交集

1、两个数组的交集(力扣349)

// 1.利用哈希表public int[] intersection(int[] nums1, int[] nums2) {Set<Integer> numsSet = new HashSet<>();Set<Integer> resSet = new HashSet<>();for (int num : nums1){numsSet.add(num);}for (int num : nums2){if (numsSet.contains(num)){resSet.add(num);}}int[] resArray = new int[resSet.size()];int index = 0;for (int i : resSet){resArray[index ++] = i;}return resArray;}
//2.双指针public static int[] intersection3(int[] nums1, int[] nums2) {Arrays.sort(nums1);Arrays.sort(nums2);Set<Integer> set = new HashSet<>();int i = 0;int j = 0;while (i < nums1.length && j < nums2.length) {if (nums1[i] == nums2[j]) {set.add(nums1[i]);i++;j++;} else if (nums1[i] < nums2[j]) {i++;} else if (nums1[i] > nums2[j]) {j++;}}int[] ans = new int[set.size()];int index = 0;for (int value : set) {ans[index++] = value;}return ans;}
//3.二分法public static int[] intersection4(int[] nums1, int[] nums2) {Set<Integer> set = new HashSet<>();Arrays.sort(nums2);for (int target : nums1) {if (binarySearch(nums2, target)) {set.add(target);}}int index = 0;int[] ans = new int[set.size()];for (int value : set) {ans[index++] = value;}return ans;}public static boolean binarySearch(int[] num, int target) {int left = 0;int right = num.length - 1;while (left <= right) {int mid = left + (right - left) / 2;if (num[mid] == target) {return true;} else if (num[mid] < target) {left = mid + 1;} else if (num[mid] > target) {right = mid - 1;}}return false;}

2、两个数组的交集 II(力扣350)

// 1.哈希表
public int[] intersect(int[] nums1, int[] nums2) {if (nums2.length < nums1.length){return intersect(nums2, nums1);}/* 记录元素及元素出现的次数 */Map<Integer, Integer> numMap = new HashMap<>();for (int num : nums1) {numMap.put(num, numMap.getOrDefault(num, 0) + 1);}/* 记录重复元素 */List<Integer> resList = new ArrayList<>();for (int num : nums2) {if (numMap.containsKey(num) && numMap.get(num) > 0){resList.add(num);numMap.put(num, numMap.get(num) - 1);}}/* 构建返回数组*/int[] resArray = new int[resList.size()];for (int i = 0; i < resList.size(); i++) {resArray[i] = resList.get(i);}return resArray;}
//2.排序+双指针 前提:两个数组是排好序的public int[] intersect(int[] nums1, int[] nums2) {Arrays.sort(nums1);Arrays.sort(nums2);int i = 0,j = 0;int len1 = nums1.length,len2 = nums2.length;List<Integer> list = new ArrayList<>();while(i < len1 && j < len2){if(nums1[i] == nums2[j]){list.add(nums1[i]);i ++;j ++;}else if(nums1[i] < nums2[j]){i ++;}else{j ++;}}int size = list.size();int[] ans = new int[size];for(int index = 0;index < size; index++){ans[index] = list.get(index);}return ans;}

三、其他的哈希表题

1、快乐数(力扣202)

//1.普通方法//两种情况:1 最终是1  2. 陷入循环public static boolean isHappy(int n) {Set<Integer> set = new HashSet<>();//如果n不是1,而且没有陷入循环,就不停迭代while (n != 1 && !set.contains(n)){set.add(n);n = getSum(n);}return n == 1;}
//获取一个数的各个位上的数字的平方和public static int getSum(int n){int sum = 0;while (n > 0){int num = n % 10;sum += num * num;n /= 10;}return sum;}
//2.快慢指针//两种情况:如果成环,且不是1,返回falsepublic static boolean isHappy(int n) {int slow = n;int fast = getSum(n);while (fast != 1 && fast != slow){//慢指针每次走一步slow = getSum(fast);//快指针每次走两步fast = getSum(getSum(slow));}return fast == 1;}

2、两数之和(力扣1)

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

3、四数相加 II(力扣454)

//四个数组两两组合,等效成两个数组之和public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {int len = nums1.length;Map<Integer,Integer> map = new HashMap<>();for(int i = 0;i < len;i ++){for(int j = 0;j < len; j ++){map.put(nums1[i] + nums2[j],map.getOrDefault(nums1[i] + nums2[j],0) + 1);}}int count = 0;for(int i = 0;i < len;i ++){for(int j = 0;j < len; j ++){if(map.containsKey(-(nums3[i] + nums4[j]))){count += map.get(-(nums3[i] + nums4[j]));}}}return count;}

时间复杂度O(n2),空间复杂度O(n2)

4、三数之和(力扣15)

public List<List<Integer>> threeSum(int[] nums) {List<List<Integer>> resList = new ArrayList<>();if (nums == null || nums.length < 2){return resList;}Arrays.sort(nums);for (int i = 0; i < nums.length - 2; i++) {/* 最小的数大于0,直接结束 */if (nums[i] > 0){break;}/* 跳过重复值 */if (i > 0 && nums[i] == nums[i - 1]){continue;}int startIndex = i + 1;int endIndex = nums.length - 1;while (startIndex < endIndex){if (nums[startIndex] + nums[endIndex] + nums[i] == 0){resList.add(Arrays.asList(nums[startIndex], nums[endIndex], nums[i]));startIndex ++;endIndex --;while (startIndex < endIndex && nums[startIndex] == nums[startIndex - 1]){startIndex ++;}while (startIndex < endIndex && nums[endIndex] == nums[endIndex + 1]){endIndex --;}} else if (nums[startIndex] + nums[endIndex] + nums[i] < 0){startIndex ++;} else {endIndex --;}}}return resList;}

5、四数之和(力扣18)

public static List<List<Integer>> fourSum(int[] nums, int target) {List<List<Integer>> resList = new ArrayList<>();if (nums.length < 4){return resList;}/* 数组排序 */Arrays.sort(nums);int numLen = nums.length;for (int i = 0; i < numLen - 3; i++) {/* 跳过重复值 */if (i > 0 && nums[i] == nums[i - 1]){continue;}for (int j = i + 1; j < numLen - 2; j++) {/* 跳过重复值 */if (j > i + 1 && nums[j] == nums[j - 1]){continue;}int startIndex = j + 1, endIndex = numLen - 1;while (startIndex < endIndex){long curSum = (long) nums[i] + nums[j] + nums[startIndex] + nums[endIndex];if (curSum == target){resList.add(Arrays.asList(nums[i], nums[j], nums[startIndex], nums[endIndex]));startIndex ++;endIndex --;while (startIndex < endIndex && nums[startIndex] == nums[startIndex - 1]){startIndex ++;}while (startIndex < endIndex && nums[endIndex] == nums[endIndex + 1]){endIndex --;}} else if (curSum < target){startIndex ++;} else {endIndex --;}}}}return resList;}

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

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

相关文章

2.变量和常量

1.变量2.2 变量的基本使用2.3 变量的本质 2.4 变量命名规则与规范 2.5 变量拓展-数组 1.数组的基本使用 2.常量

Java并发核心基础解析

目录 一、背景 二、Java线程模型 三、Synchronized实现原理 3.1 锁的使用 3.2 解释执行 3.3 JIT执行 3.4 锁的状态 3.5 monitorenter 3.5.1 偏向锁 3.5.2 轻量级锁 3.5.3 重量级锁 3.6 monitorexit 3.6.1 偏向锁 3.6.2 轻量级锁 3.6.3 重量级 四、可见性的真相…

线程池111

线程池框图C语言线程池详解&#xff1a;从基础到实现通俗理解线程池想象你开了一家快递站&#xff0c;每天要处理很多包裹派送&#xff1a;​没有线程池​&#xff1a;每来一个包裹就雇一个新快递员&#xff0c;送完就解雇问题&#xff1a;频繁招聘解雇成本高&#xff08;线程创…

Qt-Advanced-Docking-System

直译一下 &#xff1a; 先进的停靠系统 github: mfreiholz/Qt-Advanced-Docking-System: Advanced Docking System for Qt 这是这个项目的起源 这个最后一次更新&#xff1a; githubuser0xFFFF/Qt-Advanced-Docking-System: Advanced Docking System for Qt 这是另一个人复刻…

湖南(源点咨询)市场调研 如何在行业研究中快速有效介入 中篇

我们接着起头篇来说迈克尔波特认为一个行业内存在着五种基本竞争力量&#xff0c;即潜在入侵者、替代产品、供方、需方以及行业内现有竞争者。如附图&#xff1a;即&#xff1a;同行业内现有竞争者的竞争能力、潜在竞争者进入的能力、替代品的替代能力、供应商的讨价还价能力、…

【无标题】消息队列(Message Queue)是一种**进程间通信(IPC)机制

消息队列&#xff08;Message Queue&#xff09;是一种进程间通信&#xff08;IPC&#xff09;机制&#xff0c;它允许进程通过在队列中添加和读取消息来交换数据。与管道&#xff08;命名/匿名&#xff09;相比&#xff0c;消息队列具有结构化消息、异步通信和消息持久化等特点…

mac中多版本JDK配置和切换

下载 从jdk官网下载即可&#xff0c;找到自己要用的版本。 官网&#xff1a;https://www.oracle.com/java/technologies/downloads/#jdk21-mac 我这里下载的jdk1.8和21。 根据自己芯片下载&#xff0c;一般都是m芯片。下载好后&#xff0c;点击&#xff0c;一直下一步就行&…

【JVM】流程汇总

【JVM】流程汇总【一】编译过程和内存分布【1】案例程序&#xff1a;简单的 Java 类【2】Java 编译过程&#xff1a;从.java到.class&#xff08;1&#xff09;编译命令&#xff08;2&#xff09;编译结果&#xff08;3&#xff09;字节码的作用【3】Java 运行过程&#xff1a;…

专业MP3瘦身工具WinMP3Shrink 1.1,绿色单文件,极速压缩

[软件名称]: 专业MP3瘦身工具WinMP3Shrink 1.1 [软件大小]: 1.1 MB [软件大小]: 夸克网盘 | 百度网盘 软件介绍 WinMP3Shrink 是一款免费的 MP3 压缩软件&#xff0c;能够有效减少 MP3 文件的体积&#xff0c;同时还能增强音质。即使不重新编码&#xff0c;通过移除保留空间…

LeetCode 每日一题 2025/8/4-2025/8/10

记录了初步解题思路 以及本地实现代码&#xff1b;并不一定为最优 也希望大家能一起探讨 一起进步 目录8/4 904. 水果成篮8/5 3477. 水果成篮 II8/6 3479. 水果成篮 III8/7 3363. 最多可收集的水果数目8/8 808. 分汤8/9 231. 2 的幂8/10 869. 重新排序得到 2 的幂8/4 904. 水果…

Python爬虫实战:研究Ruia框架,构建博客园文章采集系统

1. 引言 1.1 研究背景与意义 在数字化时代,数据已成为驱动科技创新与产业升级的核心生产要素。互联网作为全球最大的信息载体,蕴含着亿级结构化、半结构化与非结构化数据,这些数据在商业决策、学术研究、公共服务等领域具有不可替代的价值。网络爬虫技术作为自动获取网络公…

Office安装使用?借助Ohook开源工具?【图文详解】微软Office产品

一、问题背景 很多用户在使用 Office 软件一段时间后&#xff0c;会遇到以下问题。 二、解决方案 Ohook 是 Office 独有的可用方式&#xff0c;源自 GitHub 上的开源项目&#xff0c;代码开源&#xff08;开源地址&#xff1a;https://github.com/asdcorp/ohook&#xff09;。 …

LeetCode简单题 - 学习

力扣题库 - 简单题 - 仅记录学习 来源地址&#xff1a; 力扣 (LeetCode) 全球极客挚爱的技术成长平台 1. 两数之和 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你…

Android Camera 打开和拍照APK源码

完整下载路径: 【免费】AndroidcameraAPK完整源码(包括打开摄像头和拍照保存功能)Android10验证可完整运行资源-CSDN下载 效果: 源码: package com.example.mycamera;import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appco…

【系统分析师】软件需求工程——第11章学习笔记(上)

软件需求工程是包括创建和维护软件需求文档所必需的一切活动的过程。可分为两大工作&#xff1a;需求开发需求获取需求分析需求定义&#xff08;编写需求规格说明书&#xff09;需求验证需求管理定义需求基线处理需求变更需求跟踪在需求开发阶段需要确定软件所期望的用户类型&a…

机器学习第七课之支持向量机SVM

目录 简介&#xff1a; 一、什么是支持向量机 二、如何选取最佳的超平面 1.超平面方程 (优化目标) 2.如何寻找最优的超平面 3.举例分析 4.软间隔​编辑 三、核函数 1举例 2常用核函数 3.多项式核函数 4.高斯核函数: 四、svm的优缺点 五、支持向量机的API 六、案例…

P3232 [HNOI2013] 游走,solution

原题&#xff1a; link&#xff0c;点击这里喵。 题意&#xff1a; 给定一个 nnn 个点 mmm 条边的无向连通图&#xff0c;图无重边和自环&#xff0c;顶点从 111 编号到 nnn&#xff0c;边从 111 编号到 mmm。 小 Z 在该图上进行随机游走&#xff0c;初始时小 Z 在 111 号顶…

Docker容器部署discuz论坛与线上商城

准备 关闭防火墙&#xff0c;上下文[rootdocker ~]# systemctl disable --now firewalld[rootdocker ~]# setenforce 0下载应用yum remove runc -y ### rocky8才需要yum install -y yum-utils yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/cento…

Linux入门指南:26个基础命令全解析

目录 一.基础概念与入门 1.Linux操作系统简介 2.终端与shell的基本概念 3.命令行界面的优势 二.基础指令 1.whoami ​2.useradd/userdel/passwd ​3.pwd ​4.ls ​5.cd 6.touch 7.mkdir 8.tree 9.rmdir/rm 10.man 11.cp 12.mv 13.cat 14.le…

【后端】Java 8 特性 `User::getId` 语法(方法引用)介绍

文章目录核心概念解析&#xff1a;方法引用的四种类型&#xff1a;关键特性&#xff1a;使用场景推荐&#xff1a;何时避免使用&#xff1a;性能说明&#xff1a;在 Java 中&#xff0c; User::getId 是一种称为 方法引用&#xff08;Method Reference&#xff09; 的语法糖&a…