赞
踩
不行了,今天玩了一天没学习,到了晚上才开始刷题。。看我今晚上能不能把它刷出来!
首先切记!什么时候想到用哈希法,当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法。
遇到哈希问题首先要想到的三种数据结构:数组、set、map。关于哈希表基础可以b站上看一下青大王卓老师的视频(查找模块),当时我的数据结构就是在她那里入门的哈哈哈。
哈希表就类似于数组,下标也是从0开始,可以通过哈希函数将某个数存放在表中的某个空间里。
注:每道题前面的题号都对应力扣上的题
给定两个字符串 s
和 t
,编写一个函数来判断 t
是否是 s
的字母异位词。
注意:若 s
和 t
中每个字符出现的次数都相同,则称 s
和 t
互为字母异位词。
示例 1:
输入: s = "anagram", t = "nagaram" 输出: true
思考:第一次做哈希题,先看了一下卡哥思路,我们用哈希表来存放字符串s中字母的出现频率,之后减去字符串t中字母的出现频率,若最后表中存放的为0,则互为字母异位词。
代码实现:
- class Solution {
- public boolean isAnagram(String s, String t) {
- int []haxi=new int[26];
- for (char i:s.toCharArray()) {
- haxi[i-'a']++;
- }
- for (char i:t.toCharArray()){
- haxi[i-'a']--;
- }
- for (int i = 0; i < haxi.length; i++) {
- if(haxi[i]!=0)
- return false;
- }
- return true;
- }
- }
总结:如果用哈希表做法的话,这道题其实也挺简单的。注意遍历字符串中某单个元素的方法。
给定两个数组 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数组法
- class Solution {
- public int[] intersection(int[] nums1, int[] nums2) {
- int[] hash1 = new int[1002];
- int[] hash2 = new int[1002];
- for(int i : nums1)
- hash1[i]++;
- for(int i : nums2)
- hash2[i]++;
- List<Integer> resList = new ArrayList<>();
- for(int i = 0; i < 1002; i++)
- if(hash1[i] > 0 && hash2[i] > 0)
- resList.add(i);
- int index = 0;
- int res[] = new int[resList.size()];
- for(int i : resList)
- res[index++] = i;
- return res;
- }
- }
HashSet法
- 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];
- }
- 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);
- }
- }
-
- //方法1:将结果集合转为数组
-
- return resSet.stream().mapToInt(x -> x).toArray();
-
- //方法2:另外申请一个数组存放setRes中的元素,最后返回数组
- int[] arr = new int[resSet.size()];
- int j = 0;
- for(int i : resSet){
- arr[j++] = i;
- }
-
- return arr;
- }
- }
总结:学会如何将Array和Set集合中存放的数据转化为数组。
编写一个算法来判断一个数 n
是不是快乐数。
「快乐数」 定义为:
如果 n
是 快乐数 就返回 true
;不是,则返回 false
。
示例 1:
输入:n = 19 输出:true
思考:
这个题直接看示例就能理解了。因为不确定n未来会变成多少数,为了减少内存,首先先考虑Set方法,将求得的数字放进Set中。
那么如何进行查找呢?查找的条件是如果Set中出现了1,那么n就是快乐数。
如果一直没有出现n,那Set中的数字岂不是要一直加下去?当然不是,如果Set中出现了重复的数字,那么n就一定不是快乐数。
接下来照着这个思路写代码吧!
代码实现:
- class Solution {
- public int Nextnum(int n){
- int getnext=0;
- while(n!=0){
- int x=(n%10)*(n%10);
- getnext+=x;
- n/=10;
- }
- return getnext;
- }
- public boolean isHappy(int n) {
- Set set=new HashSet<>();
- while (n!=1){
- if(set.contains(n))
- return false;
- set.add(n); //把下一个数存储到set中
- n=Nextnum(n);
- }
- return true;
- }
- }
总结:其实这道题我刚开始做的时候是把思路想错了,我想的竟然是把每一位数存在Set里。。。总之,还是得学会思维发散啊。熟练掌握哈希法中数组法与set的灵活运用。
给定一个整数数组 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
代码实现:
- 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]; // 遍历当前元素,并在map中寻找是否有匹配的key
- if(map.containsKey(temp)){
- res[1] = i;
- res[0] = map.get(temp);
- break;
- }
- map.put(nums[i], i); // 如果没找到匹配对,就把访问过的元素和下标加入到map中
- }
- return res;
总结:好好看视频,可以知道map中每次存放的是key和value。当然我们要分配好什么是key,什么是value。例如本题中打破了以往的惯性思维,将数组元素存放到key,而将下标值存放到value里。如果set解决的是找出数组元素,那么map解决的就是不仅要找出数组元素,还要找出对应的元素下标值。这里的代码也需要着重理解。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。