day06哈希表
总结的来说,当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法。
但是哈希法也是牺牲了空间换取了时间,因为我们要使用额外的数组,set或者是map来存放数据,才能实现快速的查找。
lc242有效的字母异位词
给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。
示例 1: 输入: s = “anagram”, t = “nagaram” 输出: true
示例 2: 输入: s = “rat”, t = “car” 输出: false
说明: 你可以假设字符串只包含小写字母。
读题可以看不懂到底什么是字母异位词呢?
大白话就是 给定两个字符串 判断是否有相同的字母组成(不管顺序)
比如 abbc — bbac 这这就是一对字母异位词
因为知道这些字母只能是小写字母 而且字母的asc码都是连续的
所以可以定一个数组 大小是26 刚好能放入26个字母 用来记录字符串s里字符出现的次数。
因为asc码都是连续的 所以a到z是26个连续的数 所以将(s[i] - ‘a’)++ 求出来一个数字
同样,在便利t的时候,只需要-- 就可以了
其实也就是26个字母对应26个下标 出现一次就对应下标加一 出现的位置比如
t=‘abcdef…z’ 26个 那么依次加加操作之后就是 arr[1,1,1,1,1,1,1,1,1,1,1,1,…1] 26个1
最后检查这个数组,如果有元素不等于0 说明s或者t字符串一定有一个多了 或者少了
如果都是等于0 说明就是字母异位词
时间复杂度为O(n),空间上因为定义是的一个常量大小的辅助数组,所以空间复杂度为O(1)。
--------
也就是:
第一次便利s的时候 遇到每个字母就把他在数组对应的位置加1 表示出现过
第二次便利t的时候 遇到的时候 就把对应位置减1
如果最后结果数组都是0 代表两个字符串完全相等
public boolean isAnagram(String s, String t) {
int[] arr = new int[26];
for(int i = 0; i < s.length(); i++) arr[s.charAt(i) - 'a']++;
for(int i = 0; i < t.length(); i++) arr[t.chatAt(i) - 'a']--;
for(int c : arr){
if(c != 0) return false;
}
return true;
}
lc349两个数组的交集
> 题意:给定两个数组,编写一个函数来计算它们的交集。 > > 输入:nums1 = [4,9,5],nums2 = [9,4,9,8,4] > > 输出:[9,4] >使用set结构 定义 s1 res
s1 用于存放num1中的元素也就是 s1 = {4,9,5}
res 用于nums1和nums2经过去重之后交集部分
执行结果:
nums2[0] = 9
,s1
包含9
,添加到res
:res = {9}
nums2[1] = 4
,s1
包含4
,添加到res
:res = {9, 4}
nums2[2] = 9
,res
已经包含9
,所以不重复添加。nums2[3] = 8
,s1
不包含8
,跳过。nums2[4] = 4
,res
已经包含4
,所以不重复添加。
最终,res = {9, 4}
,这是 nums1
和 nums2
的交集。
public int[] intersection(int[] nums1, int[] nums2) {
if (nums1 == null || nums1.length == 0 || nums2 == null || nums2.length == 0) return new int[0];
// 初始化set
Set<Integer> s1 = new HashSet<>();
Set<Integer> res = new HashSet<>();
//便利num1
for(int i : nums1) s1.add(i);
// 便利num2时候需要先去重
for(int i : nums2){
if(s1.contains(i)) res.add(i);
}
//申请新数组存放结果 并且返回
int[] arr = new int[res.size()];
int index = 0;
for(int num : res) arr[index++] = num;
return arr;
}
lc202 快乐数
「快乐数」定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。如果 可以变为 1,那么这个数就是快乐数。
编写一个算法来判断一个数 <font style="color:rgba(38, 38, 38, 0.75);background-color:rgb(240, 240, 240);">n</font>
是不是快乐数。
题目中说了会 无限循环,那么也就是说求和的过程中,sum会重复出现
这道题目使用哈希法,来判断这个sum是否重复出现,如果重复了就是return false, 否则一直找到sum为1为止。
public boolean isHappy(int n) {
Set<Integer> set = new HashSet<>();
while(n != 1 && set.contains(n)){
set.add(n);
n = getNumber(n);
}
return n == 1;
}
public int getNumber(int n) {
int res = 0;
while(n > 0){
int temp = n % 10 //取出个位
res += temp * temp;
n /= 10;
}
return res;
}
lc1 两数之和
梦的开始!!!
使用map来记录数字和下标
map中的存储结构为 {key:数据元素,value:数组元素对应的下标}。
public int[] twoSum(int[] nums. int target){
int[] res = new int[2];
if(nums == null || nums.length ==0) return res;
Map<Integer, Integer> map = new HashMap<>();
for(int i = 0; i < nums.length; i++){
int temp = target - nums[i];
if(map.containsKey(temp)){
res[1] = i;
res[0] = map.get(temp);
break;
}
map.put(nums[i], i);
}
return res;
}