当前位置:   article > 正文

代码随想录Day6--哈希表part01

代码随想录Day6--哈希表part01

不行了,今天玩了一天没学习,到了晚上才开始刷题。。看我今晚上能不能把它刷出来!

哈希表理论基础

首先切记!什么时候想到用哈希法,当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法。  

遇到哈希问题首先要想到的三种数据结构:数组、set、map。关于哈希表基础可以b站上看一下青大王卓老师的视频(查找模块),当时我的数据结构就是在她那里入门的哈哈哈。

哈希表就类似于数组,下标也是从0开始,可以通过哈希函数将某个数存放在表中的某个空间里。

开始做题!

注:每道题前面的题号都对应力扣上的题

242.有效的字母异位词(简单)

给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。

注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。

示例 1:

输入: s = "anagram", t = "nagaram"
输出: true

思考:第一次做哈希题,先看了一下卡哥思路,我们用哈希表来存放字符串s中字母的出现频率,之后减去字符串t中字母的出现频率,若最后表中存放的为0,则互为字母异位词。

代码实现:

  1. class Solution {
  2. public boolean isAnagram(String s, String t) {
  3. int []haxi=new int[26];
  4. for (char i:s.toCharArray()) {
  5. haxi[i-'a']++;
  6. }
  7. for (char i:t.toCharArray()){
  8. haxi[i-'a']--;
  9. }
  10. for (int i = 0; i < haxi.length; i++) {
  11. if(haxi[i]!=0)
  12. return false;
  13. }
  14. return true;
  15. }
  16. }

总结:如果用哈希表做法的话,这道题其实也挺简单的。注意遍历字符串中某单个元素的方法。

349.两个数组的交集(简单)

给定两个数组 nums1 和 nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。

示例 1:

输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2]

思考:这个题借用上题的方法,用哈希问题中的数组法很快就能做出来。当然用set方法比用数组更好,HashSet可以处理哈希法中出现数据量极大的情况,而数组法比较浪费内存,可以参考数组与List的比较。但我之前没接触过set,所以用数组法写了一遍。这里用的是卡尔的代码。

set分类:set、multi-set(这两类的底层实现为红黑树)、unordered-set(底层实现为哈希值)。

unordered-set做映射和取值操作的效率是最高的,所以本题可以用unordered-set来解答。

代码实现:

Hash数组法

  1. class Solution {
  2. public int[] intersection(int[] nums1, int[] nums2) {
  3. int[] hash1 = new int[1002];
  4. int[] hash2 = new int[1002];
  5. for(int i : nums1)
  6. hash1[i]++;
  7. for(int i : nums2)
  8. hash2[i]++;
  9. List<Integer> resList = new ArrayList<>();
  10. for(int i = 0; i < 1002; i++)
  11. if(hash1[i] > 0 && hash2[i] > 0)
  12. resList.add(i);
  13. int index = 0;
  14. int res[] = new int[resList.size()];
  15. for(int i : resList)
  16. res[index++] = i;
  17. return res;
  18. }
  19. }

HashSet法

  1. import java.util.HashSet;
  2. import java.util.Set;
  3. class Solution {
  4. public int[] intersection(int[] nums1, int[] nums2) {
  5. if (nums1 == null || nums1.length == 0 || nums2 == null || nums2.length == 0) {
  6. return new int[0];
  7. }
  8. Set<Integer> set1 = new HashSet<>();
  9. Set<Integer> resSet = new HashSet<>();
  10. //遍历数组1
  11. for (int i : nums1) {
  12. set1.add(i);
  13. }
  14. //遍历数组2的过程中判断哈希表中是否存在该元素
  15. for (int i : nums2) {
  16. if (set1.contains(i)) {
  17. resSet.add(i);
  18. }
  19. }
  20. //方法1:将结果集合转为数组
  21. return resSet.stream().mapToInt(x -> x).toArray();
  22. //方法2:另外申请一个数组存放setRes中的元素,最后返回数组
  23. int[] arr = new int[resSet.size()];
  24. int j = 0;
  25. for(int i : resSet){
  26. arr[j++] = i;
  27. }
  28. return arr;
  29. }
  30. }

总结:学会如何将Array和Set集合中存放的数据转化为数组。

202.快乐数(简单)

编写一个算法来判断一个数 n 是不是快乐数。

「快乐数」 定义为:

  • 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
  • 然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
  • 如果这个过程 结果为 1,那么这个数就是快乐数。

如果 n 是 快乐数 就返回 true ;不是,则返回 false 。

示例 1:

输入:n = 19
输出:true
 

思考:

这个题直接看示例就能理解了。因为不确定n未来会变成多少数,为了减少内存,首先先考虑Set方法,将求得的数字放进Set中。

那么如何进行查找呢?查找的条件是如果Set中出现了1,那么n就是快乐数。

如果一直没有出现n,那Set中的数字岂不是要一直加下去?当然不是,如果Set中出现了重复的数字,那么n就一定不是快乐数。

接下来照着这个思路写代码吧!

代码实现:

  1. class Solution {
  2. public int Nextnum(int n){
  3. int getnext=0;
  4. while(n!=0){
  5. int x=(n%10)*(n%10);
  6. getnext+=x;
  7. n/=10;
  8. }
  9. return getnext;
  10. }
  11. public boolean isHappy(int n) {
  12. Set set=new HashSet<>();
  13. while (n!=1){
  14. if(set.contains(n))
  15. return false;
  16. set.add(n); //把下一个数存储到set中
  17. n=Nextnum(n);
  18. }
  19. return true;
  20. }
  21. }

总结:其实这道题我刚开始做的时候是把思路想错了,我想的竟然是把每一位数存在Set里。。。总之,还是得学会思维发散啊。熟练掌握哈希法中数组法与set的灵活运用。

1.两数之和

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target  的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

示例 1:

输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

思考:其实这道题吧,首先我想到的是用暴力法解决,但我们要学会优化,所以这道题最好还是用哈希法来解答。我是第一次接触map,所以直接去看的卡尔视频讲解,放个链接在这。梦开始的地方,Leetcode:1.两数之和,学透哈希表,map使用有技巧!_哔哩哔哩_bilibili

代码实现:

  1. public int[] twoSum(int[] nums, int target) {
  2. int[] res = new int[2];
  3. if(nums == null || nums.length == 0){
  4. return res;
  5. }
  6. Map<Integer, Integer> map = new HashMap<>();
  7. for(int i = 0; i < nums.length; i++){
  8. int temp = target - nums[i]; // 遍历当前元素,并在map中寻找是否有匹配的key
  9. if(map.containsKey(temp)){
  10. res[1] = i;
  11. res[0] = map.get(temp);
  12. break;
  13. }
  14. map.put(nums[i], i); // 如果没找到匹配对,就把访问过的元素和下标加入到map中
  15. }
  16. return res;

总结:好好看视频,可以知道map中每次存放的是key和value。当然我们要分配好什么是key,什么是value。例如本题中打破了以往的惯性思维,将数组元素存放到key,而将下标值存放到value里。如果set解决的是找出数组元素,那么map解决的就是不仅要找出数组元素,还要找出对应的元素下标值。这里的代码也需要着重理解。

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号