LeetCode分类刷题----哈希表篇

news2024/11/25 23:39:48

哈希表

    • 哈希表
      • 1.有效的字母异位词
        • 242.有效的字母异位词
        • 383.赎金信
        • 49.字母异位词分组
        • 438.找到字符串中所有字母异位词
      • 2.两个数组的交集
        • 349.两个数组的交集
        • 350.两个数组的交集||
      • 3.快乐数202
        • 202.快乐数
      • 4.两数之和
        • 1.两数之和
      • 5.四数相加
        • 454.四数相加||
      • 6.三数之和
        • 15.三数之和
      • 7.四数之和
        • 18.四数之和

哈希表

1.有效的字母异位词

242.有效的字母异位词

在这里插入图片描述
思路: 就是判断两个字符串包含的字母是不是一样的。我们可以用一个数组来存储这些。遍历s的时候把字符出现的个数用数组来存储,遍历t的时候再把相应的个数减去,最后判断数组里边的元素是不是都为0.

 public boolean isAnagram(String s, String t) {
         int []arr=new int[26];
         for(int i=0;i<26;i++) {
        	 arr[i]=0;
         }
         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']--;
         }
         for(int i=0;i<26;i++) {
        	 if(arr[i]!=0) {
        		 return false;
        	 }
         }
         return true;
	    
	 }

383.赎金信

在这里插入图片描述
思路:
和上一题思路一样,这道题只不过是串的范围大小的问题,后边的字符串字母可以多几个。

 public boolean canConstruct(String ransomNote, String magazine) {
		 int []arr=new int[26];
         for(int i=0;i<26;i++) {
        	 arr[i]=0;
         }
         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']--;
         }
         for(int i=0;i<26;i++) {
        	 if(arr[i]<0) {
        		 return false;
        	 }
         }
         return true;
	   }

49.字母异位词分组

在这里插入图片描述
思路:
字母异位词就是字母个数相同而排列顺序不同的字符。我们可以把字母排序好的字符串当作键,然后对应的字符串当作值,最后依次输出即可。

 public List<List<String>> groupAnagrams(String[] strs) {

	    Map<String,List<String>> map=new HashMap<String,List<String>>();
	    for(String str:strs) {
	    	char []array=str.toCharArray();
	    	Arrays.sort(array);
	    	String key=new String(array);
	    	List<String> list=map.getOrDefault(key, new ArrayList<String>());
	    	list.add(str);
	    	map.put(key,list);
	    }
	    return new ArrayList<List<String>>(map.values());
	 }

438.找到字符串中所有字母异位词

在这里插入图片描述
思路:
首先将p字符串出现的字符存在字符数组里面,定义distance表示有效字符的个数。
一直在滑动窗口里的字符数组填入right指针指向的数据,当distance满足条件时,此时可以缩小窗口了,即移动左指针,当左右指针的差值恰好等于目标字符的长度时,此时就代表子串找到了。

public static List<Integer> findAnagrams(String s, String p) {
		 //将原字符串转换成字符数组
		 char []charArrayS=s.toCharArray();
		 char []charArrayP=p.toCharArray();
		 //分别记录窗口里和原字符串字母出现的个数
		 int []winFreq=new int[26];
		 int []pFreq=new int[26];
		 for(char c:charArrayP) {
			 pFreq[c-'a']++;
		 }
		 int distance=0;//窗口里满足条件的字符串的个数
		 int begin=0;//满足条件的数组的起始位置
		 int left=0,right=0;//左右指针
		 List<Integer> result=new ArrayList<>();
		 while(right<charArrayS.length) {
			 //当右指针遇见的字符串在tFreq中没有出现,右指针继续往右移动
			  if(pFreq[charArrayS[right]-'a']==0) {
				  right++;
				  continue;
			  }
			//当遇到的这个字符,窗口内的字符个数小于目标字符个数时,distance++
			  if(winFreq[charArrayS[right]-'a']<pFreq[charArrayS[right]-'a']) {
				  distance++;
				  
			  }
			  
			  winFreq[charArrayS[right]-'a']++;
			  right++;
			  while(distance==p.length()) {
				  if((right-left)==p.length())
				  {
					  result.add(left);
				  }
				  if(pFreq[charArrayS[left]-'a']==0) {
					  left++;
					  continue;
				  }
				  if(winFreq[charArrayS[left]-'a']==pFreq[charArrayS[left]-'a']) {
					  distance--;
					  
				  }
				  winFreq[charArrayS[left]-'a']--;
				  left++;
			  }
		 }
          return result;
	    }

2.两个数组的交集

349.两个数组的交集

在这里插入图片描述
思路:
用set做:将第一个数组出现的字母存在set里,然后再遍历一次,将第二个数组也在set出现的存在result里即可,result也用set来实现,可以去重。
用数组做:只需要将对应出现的字母标志位置为1即可。

 public int[] intersection(int[] nums1, int[] nums2) {
         
	   Set<Integer> set1=new HashSet<>();
	   Set<Integer> result=new HashSet<>();
	   for(int i:nums1) {
		   set1.add(i);
	   }
	   for(int i:nums2) {
		   if(set1.contains(i)) {
			   result.add(i);
		   }
	   }
	   return result.stream().mapToInt(x->x).toArray();
	   
	 }

350.两个数组的交集||

在这里插入图片描述
思路:
用哈希表分别统计出两个数组每个字母出现的次数,然后用出现次数较小的次数加在结果数组里即可。

public  static int[] intersect(int[] nums1, int[] nums2) {
             int[] array1=new int[1005];
             int[] array2=new int[1005];
             List<Integer> result=new ArrayList<>();
             for(int i:nums1) {
            	 array1[i]++;
             }
             for(int i:nums2) {
            	 array2[i]++;
             }
             for(int i=0;i<array2.length;i++) {
            	 if(array2[i]>0&&array1[i]>0) {
            		 int number=array2[i]<array1[i]?array2[i]:array1[i];
            		 for(int j=0;j<number;j++) {
            			 result.add(i);
            		 }
            	 }
             }
             return result.stream().mapToInt(x->x).toArray();
	    
	   }

3.快乐数202

202.快乐数

在这里插入图片描述
思路:

这道题的重点就是判断数字是否会出现无限循环的情况,我们可以把每次遍历的数记录起来,然后如果出现同样的数,说明这个数字就不是快乐数。如果没有出现,就让它进入循环即可。

class Solution {
    public boolean isHappy(int n) {
           Set<Integer>record=new HashSet<Integer>();
           while(n!=1&&!record.contains(n)) {
        	   record.add(n);
        	   n=nextNumber(n);
        	   
           }
           return n==1;
	    
	   }
	   public int nextNumber(int n) {
		   int res=0;
		   while(n>0) {
			   int index=n%10;
			   res+=index*index;
			   n=n/10;
		   }
		   return res;
	   }
}

4.两数之和

1.两数之和

在这里插入图片描述
思路:
用哈希表来做,数字作为键,数字下标作为值。这样只需要遍历一遍就可以找到答案。每遍历到一个数,找出target-i是否之前遍历过,如果遍历过就返回两个下标。
至于一个元素出现两次的情况,在hashmap中这种情况,后来出现的会覆盖掉之前出现的数字。题目中要求就是只有一组解,所以这种情况就不用考虑了把。

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

	    }

5.四数相加

454.四数相加||

在这里插入图片描述
思路:
将四个数组分成两组,前两个数组a+b的值当成键存在map中,值存这个键出现的次数。然后第二组遍历寻找对应的target值即可。此时的count不应是+1,而是加上map中对应的value值。

public static int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
		   Map<Integer,Integer> maps=new HashMap<>();
		   int count=0;
		   System.out.println(Arrays.toString(nums2));
		   for(int i=0;i<nums1.length;i++) {
			   for(int j=0;j<nums2.length;j++) {
				  
				   maps.put(nums1[i]+nums2[j],maps.getOrDefault(nums1[i]+nums2[j], 0)+1);
			   }
		   }
		   for(int i=0;i<nums3.length;i++) {
			   for(int j=0;j<nums4.length;j++) {
				  int target=0-(nums3[i]+nums4[j]);
				  if(maps.containsKey(target)) {
					  count+=maps.get(target);
				  }
			   }
		   }
		   return count;

	    }

6.三数之和

15.三数之和

在这里插入图片描述
思路:
先给原始数组排好序,然后第一次遍历代表a。然后分别用两个指针来找剩下两个数字,当三个数的和大于0时,让右指针往左移,当三个数的和小于0时,让左指针往右移。当满足条件后,将满足条件的数值放进数组里即可。
去重问题:
a去重:用nums[i]和nums[i-1]来比较,因为如果和它后边的数比较会出现正好出现答案而错过去的情况,例如[-1,-1,2].
bc去重:当左指针往右走的时候,遇到和左边数值一样的情况,继续往右走即可。同理,右指针也如此。

public List<List<Integer>> threeSum(int[] nums) {
		   //保存结果集
		   List<List<Integer>> result=new ArrayList<List<Integer>>();
		   //先对数组进行排序
		   Arrays.sort(nums);
		   //第一层循环代表数字a
		   for(int i=0;i<nums.length;i++) {
			   //第一个数大于0,直接return
			   if(nums[i]>0) {
				   return result;
			   }
			   //对a进行去重,此时a应该与前一位进行比较,而不是对后一位进行比较
			   if(i>0&&nums[i]==nums[i-1]) {
				   continue;
			   }
			   int left=i+1;//left指针指向i的右一个
			   int right=nums.length-1;//right指向末尾
			   while(left<right) {
				   if((nums[i]+nums[left]+nums[right])==0) {
					   result.add(Arrays.asList(nums[i],nums[left],nums[right]));
					   //对b和c进行去重
					   while(left<right&&(nums[left]==nums[left+1])) {
						   left++;
					   }
					   while(left<right&&(nums[right]==nums[right-1])) {
						   right--;
					   }  
					   
					   left++;
					   right--;
					   
				   }else if((nums[i]+nums[left]+nums[right])<0) {
					   left++;
				   }else if((nums[i]+nums[left]+nums[right])>0) {
					   right--;
				   }
			   }
		   }
		   return result;

	    }

7.四数之和

18.四数之和

在这里插入图片描述
思路
和三数之和思路一样,只不过又多套了一层循环,剪枝操作时要注意负数的情况。

public List<List<Integer>> fourSum(int[] nums, int target) {

		List<List<Integer>> result = new ArrayList<List<Integer>>();
		Arrays.sort(nums);
		for (int k = 0; k < nums.length; k++) {
			// 剪枝操作,如果nums[k]大于0,并且nums[k]大于target的话,可以直接return了。为啥要target大于0呢,因为如果是负数的情况,会出现两个数相加越来越小的情况
			if (nums[k] > 0 && nums[k]>target) {
				return result;
			}
			// 去重操作,第一层去重k
			if (k > 0 && nums[k] == nums[k - 1]) {
				continue;
			}
			for (int i = k + 1; i < nums.length; i++) {
				// 第二层剪枝操作 java不用第二层剪枝了
//				if ((nums[k] + nums[i]) >=0 &&(nums[k] + nums[i])>target) {
//					return result;
//				}
				// 第二层去重操作
				if (i > k + 1 && nums[i] == nums[i - 1]) {
					continue;
				}
				int left = i + 1;
				int right = nums.length - 1;
				while (left < right) {
					if ((nums[k] + nums[i] + nums[left] + nums[right]) == target) {
						result.add(Arrays.asList(nums[k], nums[i], nums[left], nums[right]));
						// 对b和c进行去重
						while (left < right && (nums[left] == nums[left + 1])) {
							left++;
						}
						while (left < right && (nums[right] == nums[right - 1])) {
							right--;
						}

						left++;
						right--;

					} else if ((nums[k] + nums[i] + nums[left] + nums[right]) < target) {
						left++;
					} else if ((nums[k] + nums[i] + nums[left] + nums[right]) > target) {
						right--;
					}
				}
			}
		}
		return result;

	}

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

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

相关文章

ARM 实时时钟 RTC

一、何为实时时钟 (1) real time clock&#xff0c;真实时间&#xff0c;就是所谓的xx年x月x日x时x分x秒星期x. (2) RTC是 SoC 中一个内部外设&#xff0c;RTC 有自己独立的晶振提供 RTC 时钟源&#xff08;32.768KHz&#xff09;&#xff0c;内部有一些寄存器用来记录时间&am…

微信小程序登陆,后端接口实现 - springboot

登录流程 1、通过调用wx.login获取登录凭证&#xff08;code&#xff09; uni-app通过调用uni.login 2、前端将code提交给服务器&#xff0c;springboot访问 auth.code2Session&#xff0c;使用 code 换取 openid、unionid、session_key 等信息。 3、完成登录操作&#xff0…

数学计算-C语言实现

任务描述 计算如下公式的值: 其中π=3.1415926 本关知识 C语言常用数学函数及其用法 在使用C语言数学函数时候,应该在该源文件中使用以下命令行包含库文件: #include <math.h> 或 #include "math.h" 本题中用到的C语言数学函数如下: abs函数: 求整型…

Pytorch模型自定义数据集训练流程

文章目录Pytorch模型自定义数据集训练流程1、任务描述2、导入各种需要用到的包3、分割数据集4、将数据转成pytorch标准的DataLoader输入格式5、导入预训练模型&#xff0c;并修改分类层6、开始模型训练7、利用训好的模型做预测Pytorch模型自定义数据集训练流程 我们以kaggle竞…

交互与前端20 APIFunc.DataBase监控

说明 APIFunc.DataBase的第一版有一个监控一直在做agg,造成数据库的无谓消耗,所以一定得修补。在修补的同时,做了一些主要的修改: 1 【自增ID】给Mongo的In和Out增加了数据的自动编号和随机数生成。2 【使用缓存】通过Redis缓存,极大的的减轻了Mongo(主库)的负担这样,使得…

Kruskal重构树学习笔记(C++)

Kruskal重构树学习笔记 提示&#xff1a; 学习Kruskal重构树之前建议先了解一下Kruskal算法&#xff0c;虽然不了解这个影响不会很大 但一定要了解一下并查集的算法 接下来如果想要应用Kruskal重构树&#xff0c;一定要了解一下LCA算法 什么是Kruskal重构树 这里先简单说…

exec函数族详解

文章目录exec介绍exec族execl函数execlp函数execv函数exec介绍 通过命令查看帮助&#xff1a;man 3 exec exec 函数族的作用是根据指定的文件名找到可执行文件&#xff0c;并用它来取代调用进程的内容&#xff0c;换句话说&#xff0c;就是在调用进程内部执行一个可执行文件。…

基于多线程版本的定时器

定时器 1)咱们前面学习过的阻塞队列&#xff0c;相比于普通的队列线程安全&#xff0c;相比于普通的队列起到一个更好的阻塞效果 2)虽然使用阻塞队列&#xff0c;可以达到销峰填谷这样的一个效果&#xff0c;但是峰值中有大量的数据涌入到队列中&#xff0c;如果后续的服务器消…

教程:Flutter 和 Rust混合编程,使用flutter_rust_bridge自动生成ffi代码

实践环境&#xff1a;Arch Linuxflutter_rust_bridge官方文档Flutter环境配置教程 | Rust环境配置教程记录使用flutter_rust_bridge遇到的一些坑。假设已经我们配置了Fluuter与Rust环境现在直接使用flutter_rust_bridge模板创建自己的项目运行&#xff1a;git clone https://gi…

W13Scan 扫描器挖掘漏洞实践

一、背景 这段时间总想捣鼓扫描器&#xff0c;发现自己的一些想法很多前辈已经做了东西&#xff0c;让我有点小沮丧同时也有点小兴奋&#xff0c;说明思路是对的&#xff0c;我准备站在巨人的肩膀去二次开发&#xff0c;加入一些自己的想法&#xff0c;从freebuf中看到W13Scan…

进程调度模块

目录 1.进程介绍 2.进程调度 2.1.进程状态 2.2.进程调度函数 ---schedule 2.3.进程切换函数 ---switch_to&#xff08;&#xff09; 1.进程介绍 在进程模块里面&#xff0c;我们知道了进程就是一个task_struct的结构体&#xff0c;里面含有进程的各种信息。进程存放在进程…

AppScan被动手动探索扫描

系列文章 AppScan介绍和安装 AppScan 扫描web应用程序 第三节-AppScan被动手动探索扫描 被动式扫描&#xff1a;浏览器代理到AppScan&#xff0c;然后进行手工操作&#xff0c;探索产生出的流量给AppScan进行扫描。 他的优点是&#xff1a;扫描足够精准&#xff0c;覆盖率更…

注册中心和负载均衡(黑马SpringCloud笔记)

注册中心和负载均衡 目录注册中心和负载均衡一、服务远程调用1. RestTemplate2. 服务调用关系3. 远程调用的问题二、注册中心1. Eureka注册中心1.1 搭建Eureka注册中心1.2 服务注册1.3 服务拉取1.4 小结2. nacos注册中心2.1Nacos搭建2.2 服务注册2.3 服务拉取2.4 服务分级存储模…

虹科新闻 | 虹科与丹麦Eupry正式建立合作伙伴关系

近期&#xff0c;虹科与丹麦Eupry正式建立合作伙伴关系。未来&#xff0c;虹科与Eupry将共同关注最具创新性和稳定性的解决方案&#xff0c;为客户提供温度记录仪、温湿度记录仪、Mapping温度分布验证服务、以及基于云的温湿度自动监测系统。 虹科非常高兴欢迎并宣布我们的新合…

【Linux】基础:进程信号

【Linux】基础&#xff1a;进程信号 摘要&#xff1a;本文将会从生活实际出发&#xff0c;由此掌握进程信号的学习过程&#xff0c;分别为信号的产生、信号的传输、信号的保存和信号的处理&#xff0c;最后再补充学习信号后方便理解的其他概念。 文章目录【Linux】基础&#xf…

echarts柱状图值为0时不显示以及柱状图百分比展示

echarts柱状图值为0时不显示以及柱状图百分比展示 1.效果展示 2.代码 <template><div id"container"><div id"main"></div></div> </template> <script>import * as echarts from echarts import * as lodash…

(JVM)浅堆深堆与内存泄露

​浅堆深堆与内存泄露 1. 浅堆&#xff08;Shallow Heap&#xff09; 浅堆是指一个对象所消耗的内存。在 32 位系统中&#xff0c;一个对象引用会占据 4 个字节&#xff0c;一个 int 类型会占据 4 个字节&#xff0c;long 型变量会占据 8 个字节&#xff0c;每个对象头需要占用…

01.【Vue】Vue2基础操作

一、Vue Vue (读音 /vjuː/&#xff0c;类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是&#xff0c;Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层&#xff0c;不仅易于上手&#xff0c;还便于与第三方库或既有项目整合。另一方面&…

十五天学会Autodesk Inventor,看完这一系列就够了(七),工程图纸

众所周知&#xff0c;Autocad是一款用于二维绘图、详细绘制、设计文档和基本三维设计&#xff0c;现已经成为国际上广为流行的绘图工具。Autodesk Inventor软件也是美国AutoDesk公司推出的三维可视化实体模拟软件。因为很多人都熟悉Autocad&#xff0c;所以再学习Inventor&…

自动化测试 | 这些常用测试平台,你们公司在用的是哪些呢?

本文节选自霍格沃兹测试学院内部教材 测试管理平台是贯穿测试整个生命周期的工具集合&#xff0c;它主要解决的是测试过程中团队协作的问题。在整个测试过程中&#xff0c;需要对测试用例、Bug、代码、持续集成等等进行管理。下面分别从这四个方面介绍现在比较流行的管理平台。…