leetcode算法练习
242.有效的字母异位词
题目链接
遇到哈希问题一般就想到:
- 数组——哈希值较小 且范围可控
- set——哈希值较大或数值很分散
- map——需要k对应value
思路:
本题说了只有小写字母组成 即a~z(26个) 同时a~z的下标是连续的 那么我们就可以将a对应到数组下标为0的位置,z对应到数组下标为25的位置
遍历第一个字符串出现的字母频率 存入定义好的hash[26]数组中 遍历第二个字符串每个字母的出现频率 对应地到hash数组中做减法 那么当hash数组中都是0 那么意味着这两个字符串是有效的字母异位词
class Solution {
public boolean isAnagram(String s, String t) {
if (s.length() != t.length()) {
return false;
}
// 定义数组 默认都是0
int[] record = new int[26];
// 遍历第一个字符串
for (int i = 0; i < s.length(); i++) {
// 每个字母-a 那么就是算出它对应在数组中的下标值
record[s.charAt(i) - 'a']++;
}
// 没必要再定义一个新的数组 然后两个数组作比较 这样就慢了
// 遍历第二个字符串
for (int i = 0; i < t.length(); i++) {
// 对应的下标位置的值-1
record[t.charAt(i) - 'a']--;
}
// 判断数组中是否都是0
for (int count: record) {
if (count != 0) {
return false;
}
}
return true;
}
}
349. 两个数组的交集
题目链接
注意:本题要求的交集是需要去重的
- 本题要求中表示,,数的值不会超过1000,故选择使用数组来解决较好——但此次解题还是选择使用set(这样也可以应对数值较大时的情况)
- 为什么会想到使用哈希呢? 哈希适用于给你一个元素 判断这个元素是否出现过
思路:
将第一个数组nums1转化为哈希表,即所有数值放入哈希表里,再遍历第二个数组nums2,看nums2里的每一个元素是否在哈希表中出现过,若出现过就放入result集合里(集合去重)
import java.util.HashSet;
import java.util.Set;
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
if (nums1 == null || nums1.length == 0 || nums2 == null || nums2.length == 0) {
return new int[0];
}
// 数组1要变为的哈希表
Set<Integer> set1 = new HashSet<>();
// 结果集 会自动去除
Set<Integer> resSet = new HashSet<>();
// 遍历数组1
for (int i : nums1) {
set1.add(i);
}
// 遍历数组2的过程中判断哈希表中是否存在该元素
for (int i : nums2) {
if (set1.contains(i)) {
// 若有存在的元素就存入结果集中
resSet.add(i);
}
}
// 将结果几何转为数组
return resSet.stream().mapToInt(x -> x).toArray();
}
}
202. 快乐数
题目链接
注意:本题说到数会无限循环——即在求和的过程中 sum会重复出现——判断数据是否重复想到哈希!
思路:
使用哈希法 来判断这个sum是否重复出现 如果重复了就是return false 否则一直找到sum为1为止。
class Solution {
public boolean isHappy(int n) {
// 设置set 保证sum存入时不重复
Set<Integer> record = new HashSet<>();
// 判断record中是否已经存在相同的数值 若没有则加入
while (n != 1 && !record.contains(n)) {
record.add(n);
n = getNextNumber(n);
}
// 判断返回结果
return n == 1;
}
// 取各个位上的数值 并平方
private int getNextNumber(int n) {
int res = 0;
while (n > 0) {
int temp = n % 10;
res += temp * temp;
n = n / 10;
}
return res;
}
}
1. 两数之和
题目链接
思路:
- 假设数组为:2 7 3 6 需要得到结果9 那么遍历到3时 我们要去判断是否在前面遍历过6——那么判断元素是否存在过就想到哈希法
- 把遍历过的元素都加入一个集合,每次遍历到新的数的时候就去集合中判断我们需要寻找的元素是否在这个集合里出现过
- 集合选择使用什么数据结构 数组/set/map? 要判断是否存在过还要知晓其在原来数组中的下标位置——选择使用map结构(利用其key 元素 对应存放value 下标)
- 为什么是元素作key? 因为要查找的是元素是否出现过 map的作用就是能够最快速地找到key是否出现过
class Solution {
public int[] twoSum(int[] nums, int target) {
int[] res = new int[2];
if(nums == null || nums.length == 0){
return res;
}
// 定义存放遍历过元素的map
Map<Integer, Integer> map = new HashMap<>();
// 遍历数组
for(int i = 0; i < nums.length; i++){
// 求出现在遍历的数 要凑够target的数是多少
int temp = target - nums[i];
// 在map中判断是否有temp存在 即之前是否遍历到过temp
if(map.containsKey(temp)){
// 若有temp存在 则将temp的下标和目前遍历的数的下标
res[1] = i;
res[0] = map.get(temp);
}
// 将现在已经遍历的数存入map 再往后遍历
map.put(nums[i], i);
}
// 返回结果集
return res;
}
}