JAVA二刷-Day6 | 哈希表 242.有效的字母异位词, 349. 两个数组的交集, 202. 快乐数, 1. 两数之和
当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法。
有效的字母异位词
LeetCode题目链接:https://leetcode.cn/problems/valid-anagram/
解题思路
先看题目,可以看成统计两个字符串在长度相同的情况下每个字母出现的次数是否相等。
因此,直接建立两个数组作为两个字符串的哈希表进行存储,并对哈希表进行逐个对比。注意,在构建哈希表时要对哈希表进行初始化,否则随机初始化会引入异常值,使得哈希表查询异常。
注意java中获取string中字符使用的是charAt(index)方法,同时数组的长度为.length,不加()。
代码如下:
class Solution {
public boolean isAnagram(String s, String t) {
int[] hashMap = new int[27];
for (int i = 0; i < s.length(); i++) {
hashMap[s.charAt(i) - 'a']++;
}
for (int j = 0; j < t.length(); j++) {
hashMap[t.charAt(j) - 'a']--;
}
for (int k = 0; k < hashMap.length; k++) {
if (hashMap[k] != 0){
return false;
}
}
return true;
}
}
两个数组的交集
LeetCode题目链接:https://leetcode.cn/problems/intersection-of-two-arrays/
解题思路
计算交集同理,构造出一个数组的哈希表,用另一个数组进行查找,如果查询值大于0则说明属于交集元素。
特别注意,因为要求交集元素唯一,所以在查询到一次后,该处元素应该不再被查询,代码上将查询后的哈希值赋值为0。
注意哈希set的java构造方法为Set < < <Object > > >,其中int需要更换为包装类形式的Integer。对Set中元素查找使用contains(value),添加元素使用add(value)。
如果需要转数组形式,一种方法是构建一个set.size()大小的新数组,然后按序放入元素。否则可以直接使用jdk1.8以后的方法,用stream流来转化:reSet.stream().mapToInt(x -> x).toArray();
具体代码如下:
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
if (nums1.length == 0 || nums2.length == 0) {
return new int[0];
}
Set<Integer> set1 = new HashSet();
Set<Integer> reSet = new HashSet();
for (int i: nums1) {
set1.add(i);
}
for (int j: nums2) {
if (set1.contains(j)) {
reSet.add(j);
}
}
return reSet.stream().mapToInt(x -> x).toArray();
}
}
快乐数
LeetCode题目链接:https://leetcode.cn/problems/happy-number/
解题思路
「快乐数」定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。如果 可以变为1,那么这个数就是快乐数。
当无限循环的时候,可以看作当数值出现重复时说明进入了循环,此时即可得知是否为快乐数。同时,为了方便数值的拆分计算,可以先把数值转换为string字符串再进行拆分处理。
java的转string方法为String.valueOf()。
具体代码如下:
class Solution {
public boolean isHappy(int n) {
Set<Integer> setHappy = new HashSet();
int temp;
while (!setHappy.contains(n)) {
setHappy.add(n);
String num = String.valueOf(n);
temp = 0;
for (int i = 0; i < num.length(); i++) {
temp += Math.pow(num.charAt(i) - '0', 2);
}
if (temp == 1) {
return true;
}
n = temp;
}
return false;
}
}
两数之和
LeetCode题目链接:https://leetcode.cn/problems/two-sum/
解题思路
先看题目,要求序号不重复的前提下进行判定两数之和。因此可以在一次循环中,想办法保存之前循环过元素的值和索引。然后每次循环对之前的元素进行查询匹配。
因此涉及到查询,可以使用哈希表进行存储,因为要输出索引,因此存储时应当存储数值和索引两个值的pair。此时查询应使用containsKey来查询索引值。get来获取对应key的val值。
如果需要添加k-v对,可以使用put(k,v)。
代码如下:
class Solution {
public int[] twoSum(int[] nums, int target) {
int[] result = new int[2];
if (nums.length == 0) return result;
Map<Integer, Integer> numsMap = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
if (numsMap.containsKey(target - nums[i])) {
result[1] = i;
result[0] = numsMap.get(target - nums[i]);
return result;
}
numsMap.put(nums[i], i);
}
return result;
}
}