LeetCode 1
思路
- 这是很多朋友们
噩梦梦想的起点,我们可以暴力双层for循环,但今天我要介绍的是另外一种方法——HashMap法,我会把暴力的代码贴在下方,但这里我们就不介绍它的思路了 - 把每次遍历数组经过的数放入map中
- 判断target减去此时遍历经过的数后的差值map中是否存在,因为如果差值存在于map中,那么就说明数组中含有这个数,也就是说有那么一对数相加=target
- 找到差值所在的下标
注意点
- 我们在将键值对存放进map的时候要注意,因为这道题我们实际上要找的是数的下标而非数的本身,而map的get方法获取的是对应key的value,因此我们此时要把数作为key,把它对应的下标作为value,便于查找和获取下标
- 由于原数组是升序序列,因此我们在为结果数组赋值时要注意此时正在遍历的数是res数组的1下标所在位置,而差值所在的是0下标,因为差值是已经遍历过的数字,那么它在原数组中的下标一定更小
代码
暴力
class Solution {
public int[] twoSum(int[] nums, int target) {
int[] res = new int[2];
for (int i = 0; i < nums.length; i++) {
for (int j = i + 1; j < nums.length; j++) {
if (nums[i] + nums[j] == target) {
res[0] = i;
res[1] = j;
}
}
}
return res;
}
}
HashMap
class Solution {
public int[] twoSum(int[] nums, int target) {
int[] res = new int[2];
if(nums.length < 2) {
return res;
}
HashMap<Integer, Integer> map = new HashMap<>();
for(int i = 0; i < nums.length; i++) {
int tmp = target - nums[i]; //找到差值
if(map.containsKey(tmp)) { //因为此时key才是数的大小,因此是containsKey
res[1] = i;
res[0] = map.get(tmp); //找到此时差值对应的下标
break;
}
//由于要找的值为下标,因此其实此时下标才是value,而值是key
map.put(nums[i], i);
}
return res;
}
}
LeetCode 202
思路
- 由于文章中说非快乐数是无限循环的,由此我们就可以想到,我们可以使用set,将每一次平方和的值保存起来
- 每新获得一次平方和,我们就在set中寻找该值是否已经存在过,如果已经存在过,那么就说明该数一定不是快乐数
- 如果最后数可以通过各数平方和操作后=1,那么就跳出循环,该数为快乐数,这里就不详细介绍如何取各位数并求平方和了,这个比较基础
注意点
- n != 1与 !set.contains(n)应该是同时成立的
- 注意每一次新n的值要覆盖原n喔
代码
class Solution {
public boolean isHappy(int n) {
HashSet<Integer> set = new HashSet<>();
while(n != 1 && !set.contains(n)) {
set.add(n);
n = getNextNumber(n);
}
return n==1;
}
//求此时n的各位数的平方和
public static int getNextNumber(int n) {
int res = 0;
while(n > 0) {
int tmp = n % 10;
res += tmp * tmp;
n /= 10;
}
return res;
}
}
LeetCode 242
思路
-
因为一个只有26个字母,这是有限值,此题我们选用数组来实现哈希表
-
先遍历s字符串统计其中每个字母出现的次数
-
遍历t字符串中每个字符,并将其对应的次数-1
-
统计数组中的次数,如果有!=0的,那么就说明不是字母异位词
注意点
- 如果一开始两个字符串的长度都不相等可以直接说明它们不是异位词,可以提高运行时间
- 可以以-'a'作为基准来存放字母的次数
代码
class Solution {
public boolean isAnagram(String s, String t) {
if(s.length() != t.length()) {
return false;
}
//存放26个字母的数组
int[] record = new int[26];
for(int i = 0; i < s.length(); i++) {
record[s.charAt(i)-'a']++;
}
for(int i = 0; i < t.length(); i++) {
record[t.charAt(i)-'a']--;
}
for(int count: record) {
if(count != 0) {
return false;
}
}
return true;
}
}
LeetCode 349
思路
- 因为题目中强调了结果是唯一的,我们可以使用HashSet,保证数不重复
- 先把nums1中的数全部放进一个set中
- 判断nums2中的数是否存在于set中,如果存在就另外又放进一个set中,可以保证结果的唯一性
注意点
- 结果数组的长度必须与结果集合的大小一样,这样才不会有多余结果
- 返回值必须要将set转换为数组才能满足题目要求的返回值
代码
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
HashSet<Integer> set = new HashSet<>();
HashSet<Integer> resSet = new HashSet<>();
int len1 = nums1.length;
int len2 = nums2.length;
for(int i = 0; i < len1; i++) {
set.add(nums1[i]);
}
//判断nums2中是否存在nums1中的数
for(int i = 0; i < len2; i++) {
if(set.contains(nums2[i])) {
resSet.add(nums2[i]);
}
}
int[] res = new int[resSet.size()];
int count = 0;
//将set转换为对应的数组
for(int val: resSet) {
res[count++] = val;
}
return res;
}
}
总结
今天主要是关于哈希表的应用,set只有值且自然去重,map是键值对,键不可重复,值可重复,对于查找需求比较大的情况下建议使用哈希表