哈希表理论基础、有效的字母异位词、两个数组的交集、快乐数、 两数之和
哈希表理论基础
哈希表能解决什么问题呢,一般哈希表都是用来快速判断一个元素是否出现集合里。
哈希法一般会有如下三种数据结构:
- 数组
- set (集合)不重复,无序
- map(映射) <K, V> 不重复,无序
哈希法牺牲了空间换取了时间,因为要使用额外的数组,set或者是map来存放数据,才能实现快速的查找。
遇到需要判断一个元素是否出现过的场景也应该第一时间想到哈希法!
一、有效的字母异位词
力扣连接:242. 有效的字母异位词(简单)
可以利用一个长度为26的数组,存放a-z字母的数量
1.图解步骤
关键点:
- 首先需要创建长度为26的数组,如图所示
- s数组做相加,t数组做相减
2.代码
使用数组:
class Solution {
public boolean isAnagram(String s, String t) {
int sLen = s.length();
int tLen = t.length();
if (sLen!=tLen) return false;
int[] ss = new int[26];
for(int i=0;i<sLen;i++){
ss[s.charAt(i)-'a']++;
}
for(int i=0;i<sLen;i++){
ss[t.charAt(i)-'a']--;
if(ss[t.charAt(i)-'a']<0){
return false;
}
}
return true;
}
}
使用map:
class Solution {
public boolean isAnagram(String s, String t) {
Map<Character, Integer> map = new HashMap<>();
char[] ch_long;
char[] ch_short;
//先记录长度较长的字符串
if(s.length()>=t.length()){
ch_long = t.toCharArray();
ch_short = s.toCharArray();
}else{
ch_long = s.toCharArray();
ch_short = t.toCharArray();
}
for(char c: ch_long){
map.put(c, map.getOrDefault(c,0)+1);
}
for(char c: ch_short){
if(map.get(c)==null){
return false;
}
map.put(c, map.get(c)-1);
if(map.get(c)<0){
return false;
}
}
return true;
}
}
二、两个数组的交集
力扣连接:349. 两个数组的交集(简单)
由于题目确定返回数组的值唯一,可以考虑用Set
1.图解步骤
关键点:
- 利用Set不可重复的特性,得到值唯一的哈希表
- Set 转 int[] => set.stream().mapToInt(x->x).toArray();
2.代码
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
Set<Integer> set = new HashSet<>();
Set<Integer> res = new HashSet<>();
for(int i : nums1){
set.add(i);
}
for(int j:nums2){
if(set.contains(j)){
res.add(j);
}
}
int[] result = res.stream().mapToInt(x->x).toArray();
return result;
}
}
三、快乐数
力扣连接:202. 快乐数(简单)
1.图解步骤
暂无
关键点:
- 每次sum的值均记录在Set中,如果sum再次记录Set时已存在,即会出现死循环的情况,即不是快乐数
- 数字获取个、十、百、千等位上数时,%10 + /10 是个好方法。
2.代码
class Solution {
public boolean isHappy(int n) {
Set<Integer> set = new HashSet<>();
while(n!=1){
int sum = 0;
while(n>0){
sum += Math.pow(n%10,2);
n /= 10;
}
if(set.contains(sum)){
return false;
}
set.add(sum);
n=sum;
}
return true;
}
}
四、两数之和
力扣连接:1. 两数之和(简单)
很明显暴力的解法是两层for循环查找,时间复杂度是O(n^2)。
为了减少时间复杂度,使用map
1.图解步骤
关键点:
- 利用HashMap差值,map存<k,v> ---- <数组的值,索引>
2.暴力解法 && map快速解法
代码:
class Solution {
public int[] twoSum(int[] nums, int target) {
// int len = nums.length;
// for(int i = 0;i<len-1;i++){
// for(int j = i+1;j<len;j++){
// if(target == nums[i]+nums[j]){
// return new int[]{i,j};
// }
// }
// }
// return null;
Map<Integer, Integer> map = new HashMap<>();
for(int i = 0;i<nums.length;i++){
int temp = target-nums[i];
if(map.containsKey(temp)){
return new int[]{i,map.get(temp)};
}
map.put(nums[i], i);
}
return null;
}
}
总结
善于利用Set、Map能解决判断一个元素是否出现过的场景,应该第一时间想到哈希法!