leetcode刷题之哈希之基本数据结构使用

242.有效的字母异位词


普通版

public 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']++;
 	                        arr[t.charAt(i)-'a']--;
 			}
 			
 			for(int i=0;i<26;i++) {
 				if(arr[i]!=0)
 				return false;
 			}
 			return true;	
 	}

进阶版

	if(s.length()!=t.length()) {
 			return false;
 		}
 		Map<Character,Integer> table=new HashMap<Character,Integer>();
 		for(int i=0;i<s.length();i++) {
 			char ch=s.charAt(i);
 			table.put(ch, table.getOrDefault(ch,0)+1);
 		}
 		for(int i=0;i<t.length();i++) {
 			char ch=t.charAt(i);
 			table.put(ch, table.getOrDefault(ch, 0)-1);
 			if(table.get(ch)<0) {
 				return false;
 			}
 		}
 		return true}

思路简述

这个题其实就是看两个字符串所包含字母是否相同,关键就是利用哈希表的思想来解答,设置一个长度为26的数组当作哈希表。每一个下标存储的内容代表对应字母出现次数。然后判断遍历完两个字符串之后,会不会有存储的内容不为0,如果有,则返回false;
进阶版的问如果含有unicode怎么办,解决办法就是用map进行存储。

383.赎金信(上面题的轻微变异)

public boolean canconstruct(String r,String m) {//r为ransomNote,m为magazine
	int[] ans=new int[26];//数组哈希映射
	for(int i=0;i<m.length();i++) {//注意,要先对m进行判断
		ans[m.charAt(i)-'a']++;
	}
	for(int j=0;j<r.length();j++) {
		ans[r.charAt(j)-'a']--;
		if(ans[r.charAt(j)-'a']<0) {
			return false;
		}
	}
	return true;
}

解题步骤

1.设立26位字母映射哈希数组。
2.先对m进行遍历,其包含的字母对应加一。
3.然后对r进行遍历,其包含的字母对应减一。
4.判断哈希数组是否有值小于0,如果有则返回false。 注意:需要先对m进行判断,因为m包含的数据更多,如果符合条件,m一定含有r,而r不一定含有m。如果先判断r,那么m中有而r中没有的字符也会被判断错误。

202.快乐数

1.哈希法

public int getInt(int num){
	int sum=0;
	int ans;
	while(num>0) {
		ans=num%10;
		num/=10;
		sum+=ans*ans;
	}
	return sum;	
}
public boolean isHappy1(int num) {
	Set<Integer> table=new HashSet<>();
	while(num!=1&&!table.contains(num)) {//数字既不等于1,而且又没有出现过
		if(!table.contains(num)) {
			table.add(num);
		}
		num=getInt(num);
	}
	return num==1;
}

思路简述

分析题目可知,数字要么最后到达1,要么一直困在一个循环里。所以实质上是判断会不会出现循环。哈希法的关键就在于设立一个set来进行判断,看看数字是否已经出现过,如果出现过,那么就注定出现循环了。

2.快慢指针法

public int getInt(int num){
	int sum=0;
	int ans;
	while(num>0) {
		ans=num%10;
		num/=10;
		sum+=ans*ans;
	}
	return sum;	
}
public boolean isHappy(int num){
	int fast=getInt(num);
	int slow=num;
	while(fast!=1&&fast!=slow) {
		slow=getInt(slow);
		fast=getInt(getInt(fast));//注意fast指针设置两倍速的方式
	}
	return fast==1;
}

思路简述

本题实际上是对是否会有循环的判断,也就是对是否会出现环的一个判断,那么就可以想起来用快慢指针方法进行判断的思路,如果出现环,那么快慢指针就会相遇。按照这个基本思路进行求解

349.两个数组的交集

public int[] interSection(int[] nums1,int[] nums2) {
	
	Set<Integer> set1=new HashSet<Integer>();
	Set<Integer> set2=new HashSet<Integer>();
	for(int i:nums1) {
		set1.add(i);
	}
	for(int i:nums2) {
		if(set1.contains(i)) {//将nums1和nums2都有的元素保存在set2
			set2.add(i);
		}
	}
	int[] ans=new int[set2.size()];
	int count=0;
	for(int i:set2) {//将set移到数组里
		ans[count++]=i;
	}
	return ans;	
}

思路简述

这道题比较简单,就是找两个数组相同的值并存储。

总结

总结一下,当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法
但是哈希法也是牺牲了空间换取了时间,因为我们要使用额外的数组,set或者是map来存放数据,才能实现快速的查找。
如果在做面试题目的时候遇到需要判断一个元素是否出现过的场景也应该第一时间想到哈希法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值