代码随想录Day6 | 242. 有效的字母异位词,349. 两个数组的交集,202. 快乐数,1. 两数之和

Day6

前言

开始补了,不一定是一天完成的

文章:代码随想录

视频:算法公开课-跟着Carl学算法

LeetCode 242 有效的字母异位词

自己思路

大概懂了哈希的原理,但是不太会用代码实现,先看视频吧

看完讲解

没想到是直接一个数组就能实现了,牢记数组就是一个简单哈希表,当哈希值不大的时候用数组是很方便的。卡哥讲完之后感觉思路很清晰了,就是用一个26位的数组来标识s字母出现的频率,然后再去遍历t的时候,就在对应字母数组索引位置进行--,最后判断26位数组是不是每一位都为0就行。其中巧妙点在于不需要刻意去记ASCII码,将每个字母-'a',运算出来就是数组的索引值0~25,很妙

class Solution {
    public boolean isAnagram(String s, String t) {
        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 i = 0; i < record.length; i++) {
            if(record[i] != 0){
                return false;
            }
        }
        return true;
    }
}

LeetCode 349 两个数组的交集

自己思路

感觉有个大概的思路,但应该不是数组可以解决的问题,不会写

看完讲解

这道题的关键就是采用HashSet来解决,当哈希值数量多或者未知,或哈希值分散且跨度大的时候,数组将不再适合解决哈希问题,此时就可以考虑使用HashSet。这里使用HashSet还有一个好处,因为需要返回无重复的交集,HashSet具有自动去重功能完美适配。

在一开始的时候可以对数组为空(没有被初始化)或者长度为0(已经被初始化但不包含任何元素)进行一个判断,如果是这样可以直接返回一个长度为0 的数组。后面可以对nums1进行处理,将其转化为hashset,再对nums2进行处理,遍历nums2去hashset里面查看是否包含,包含的话就填入交集set中,即完成了题目要求。最后的话注意需要返回数组,我这里重新new一个数组,再采用遍历set依次填入新数组进行返回,也可以直接进行格式转换去返回(还不懂这个)

set.stream().mapToInt(x -> x).toArray();
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> hashSet1 = new HashSet<>();
        for (int i = 0; i < nums1.length; i++) {
            hashSet1.add(nums1[i]);
        }

        Set<Integer> commonHashSet = new HashSet<>();
        for (int i = 0; i < nums2.length; i++) {
            if (hashSet1.contains(nums2[i])) {
                commonHashSet.add(nums2[i]);
            }
        }

        int[] arr = new int[commonHashSet.size()];
        int j = 0;
        for (Integer e : commonHashSet) {
            arr[j] = e;
            j++;
        }
        return arr;
    }
}

LeetCode 202 快乐数

自己思路

感觉思路还挺混乱的,有递归的感觉,而且好像也没办法确认到底是几位数,每次都先求一下有几位数吗?

看完讲解

直接看着答案去写的,发现思路没有想的那么难,上面说到的问题其实可以再用一个函数去求取下一个n就能解决。这道题的关键还是采用HashSet来解决,定义一个hashset来存储每次的平方和,每传入一个数,先判断是否为1(直接就是快乐数)以及是否在hashset中存在(存在就说明平方和循环了,不可能是快乐数),然后返回n==1的结果就可以确认是不是快乐数(匹配了前面两个判断条件)。如果可以进入循环,就不断地循环向hashset中添加值,并构建一个函数去获取下一个n,不断地对n进行%10和/10,只要n大于0就一直进行,并将平方和结果返回,循此往复,其实写完感觉思路还是能理解的

class Solution {
    public boolean isHappy(int n) {
        Set<Integer> record = new HashSet<>();
        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;
    }
}

LeetCode 1 两数之和

自己思路

没有思路,看答案

看完讲解

首先本题也是用哈希表来解决,因为相当于遍历数组的时候,每遇到一个值,就去查找target减去它我们是否已经遍历过,即遇到了需要快速判断一个元素是否出现集合里,非常适配哈希法。此处使用的是HashMap,因为我们不仅仅需要存值,还需要存储索引,类似于Key-Value,所以采用map结构。这里的map,就是用来存储已经遍历过的元素的,需要注意,key存的是值,value存的是索引,因为我们是去查找某个值是否遍历过(所以作为key去查找),要返回的也是数组索引(所以作为value去存储),而且当数组多个索引位置是同一个值的时候,由于map的key的唯一性,也可以避免重复存储(会覆盖)。

代码其实就比较简单了,上来先定义个2位的数组,作为返回,如果nums数组为null或者长度为0就可以直接返回初始化的数组。后面就可以定义一个HashMap来存储遍历过的元素,遍历数组,每遍历一位就去map里面查找相加可以等于target的值,如果有,就直接将该key的value和当前位的索引存入数组返回,否则就不断将遍历的数字存入map中,如果一直未匹配上,那么返回的还是初始化的数组。

class Solution {
    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[0] = map.get(temp);
                res[1] = i;
                break;
            }
            map.put(nums[i], i);
        }
        return res;
    }
}

总结

用时:5.5h

断更很久,重新开始,哈希表没想象的那么难,虽然基本没有自己手撕出来的哈哈

HashSet的定义和操作

HashSet不允许集合中有重复的元素(自动去重)

// HashSet的定义
Set<Integer> set = new HashSet<>();

// 添加元素
set.add(element);

// 移除元素
set.remove(element);

// 检查集合是否包含某个元素
set.contains(element);

// 检查集合是否为空
set.isEmpty();

// 获取集合中元素的数量
set.size();

// 清空集合
set.clear();

// 遍历HashSet
for (Integer element : set) {
    System.out.println("Element = " + element);
}

HashMap的定义和操作

// HashMap的定义   键:Key(唯一) 值:Value
Map<Integer,Integer> map = new HashMap<>();

// 将指定的Key和Value添加到此映射
map.put(key, value);

// 返回指定Key所映射的Value
map.get(key);

// 返回指定Key所映射的Value,否则返回defaultValue
map.getOrDefault(Object key, V defaultValue)

// 从该映射中移除Key的映射
map.remove(key);

// 此映射是否包含指定Key的映射
map.containsKey(key);

// 返回此映射中的Key-Value映射关系数
map.size();

// 此映射空否
map.isEmpty();

// 遍历Map
// map.entrySet()用于返回Map中的所有键值对(Key-Value pair)的集合
// Map.Entry是Map的一个内部接口,表示Map集合中的一个实体(即一个键值对)
// entry.getKey()获取该键值对的键
// entry.getValue()获取该键值对的值
for (Map.Entry<Integer,Integer> entry : map.entrySet()){
     System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值