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

今天是刷代码随想录的day6。昨天day5元宵节休息日。今天开始了哈希表部分。对于哈希表的内容之前没有怎么学习过,所以今天的刷题主要以学习方法为主。待二刷的时候争取能够手撕代码!


哈希法

首先一个大前提:何时使用哈希法?

根据代码随想录-哈希表理论基础

当遇到要快速判断一个元素是否出现在集合里时,就要考虑使用哈希法。

当然,有些题目直接暴力解法通过几层for循环遍历也是可以解出来的,但这可能有非常大的时间复杂度。哈希法将需要判断的元素映射入哈希表中,这样就可以向数组中通过下标寻找元素一样快速定位元素,这就使得原本O(n)的时间复杂度变为O(1)。

常见的三种哈希结构为:

  • 数组:当范围可控,数值不大时,优先选用

  • set(集合):当数值很大或没有数值限制时,或数值分布很分散时

  • map(映射):当需要存放两个元素时(key,value)

下面的题目中分别用到了这三种不同的哈希结构。

242. 有效的字母异位词

题目

Leetcode-242.有效的字母异位词

解题思路--哈希法(数组)

判断t与s是否互为异位词,即判断s与t中是否每个字符出现的次数都相同。很明显可以使用哈希法。

这里由于题目中指出字符仅限小写字母a~z,因此一共有26个字符。数值固定,可以选择数组形式的哈希表。

首先,将a~z映射到数组hash[26]中,数组hash[26]中的每个元素初始值为0。其次,遍历s统计s中每个字符出现的次数,通过+1 写入hash。然后,遍历t统计t中每个字符出现的次数,将次数在hash中做减法。最后,遍历hash[26],若全部为0则两者互为异位词,返回true,否则返回false。

代码

class Solution {
    public boolean isAnagram(String s, String t) {

        int[] hash = new int[26]; //映射a~z连续26个字母

        //遍历s,加法统计s中每个字母出现的次数
        for(int i =0; i < s.length(); i++){
            hash[s.charAt(i) - 'a']++;         }
        //遍历t,减法减去t中每个字母出现的次数
        for(int i =0; i < t.length(); i++){
            hash[t.charAt(i) - 'a']--;
        }
        //hash数组中存在不为0的,则说明s和t不互为字母异位词
        /*for(int i =0; i < 26; i++){
            if(hash[i] != 0) return false;
        }*/
        for(int i : hash){
            if(i != 0){
                return false;
            }
        }
        //若hash中全都为0,则说明s和t互为字母异位词
        return true;

        //字符串a中:长度为a.lentgh(), 字符串某一位元素charAt()
        //由于a~z的ASCII码是是连续的,因此不需要记'a'的ASCII码,用s[i]-'a'即可将a~z对应到0~25
    }
}

349. 两个数组的交集

题目

Leetcode-349.两个数组的交集

解题思路--哈希法(set)

本题的数值没有限制,不像上一题一样。因此本题选择使用set。

首先,将nums1处理转为hash表set1。然后遍历nums2。查询nums2中的元素是否存在在set1中。如果存在,将set1中的该元素放入另一个hash表result中。

注意,本题要求返回去重的交集。而Java的Set集合存取无序,元素唯一,已经做到了去重。详见Java集合——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> result = new HashSet<>();

        //遍历数组1
        for(int i : nums1){
            set1.add(i);
        }

        //遍历数组2过程中判断哈希表中是否存在该元素
        for(int i : nums2){
            if(set1.contains(i)){
                result.add(i);
            }
        }
        return result.stream().mapToInt(x -> x).toArray();
    }
    /*Set存取无序,元素唯一
    HashSet在存储元素的过程中首先会去调用元素的hashCode()值,看其哈希值与已经存入HashSet的元素的哈希值是否相同,如果不同 :就直接添加到集合;如果相同 :则继续调用元素的equals() 和哈希值相同的这些元素依次去比较。如果说有返回true的,那就重复不添加;如果说比较结果都说false,那就是不重复就添加。
    */
}

202. 快乐数

题目

Leetcode-202.快乐数

解题思路--哈希法(set)

本题判断无限循环是否出现。因此使用哈希法。若出现无限循环不为快乐数,若不出现则肯定是等于1的时候跳出了,则为快乐数。

将每一次计算完每个位置数组的平方和替换掉n存入set。若set中contains这个n了,则说明出现了无限循环,那么就不是快乐数。若这个n=1,则这个数为快乐数。

代码

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;
    }
}
//cr.代码随想录

注:通过n%10 和n/10可以对一个数的每一位元素进行处理。这个方法可以用在其他题目中。

1.两数之和

题目

Leetcode-1.两数之和

解题思路--哈希法(map)

  1. 为什么本题用哈希法?

对于每一个x,我们首先查询哈希表中是否存在target-x 。然后将x插入到哈希表中,即可保证不会让x与自己匹配。

  1. 为什么用map?

因为我们需要存放两种值,分别是数组nums中的每一个元素和它们的下标。而map中有key和value,可以存放两种元素。

  1. map中key和value分别存放什么?

key存放数组nums中的每一个元素,因为需要查找target-x是否出现过。

value存放数组nums的下标,因为最后需要返回的是下标。

代码

class Solution {
    public int[] twoSum(int[] nums, int target) {
        Map<Integer, Integer> hashtable = new HashMap<Integer, Integer>();
        for (int i = 0; i < nums.length; ++i) {
            //若target-x存在
            if (hashtable.containsKey(target - nums[i])) {
                //则返回{target-x,x}
                return new int[]{hashtable.get(target - nums[i]), i};
            }
            //若target-x不存在,则将该key、value存入哈希表
            hashtable.put(nums[i], i);
        }
        //若遍历结束都没有返回,则返回空数组
        return new int[0];
    }
}

作者:LeetCode-Solution

今天的题目更多的是学习方法。二刷的时候最好能做到手撕代码。加油!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值