代码随想录算法训练营第六天 | 242.有效的字母异位词,349. 两个数组的交集,202. 快乐数,1. 两数之和

文章介绍了哈希表在解决LeetCode算法问题中的应用,包括判断字母异位词的有效性、找到两个数组的交集、判断快乐数以及寻找两数之和。通过暴力解法与哈希表优化方法的对比,展示了哈希表在提高效率和优化解决方案上的优势。
摘要由CSDN通过智能技术生成

哈希表理论基础

哈希表理论基础

LeetCode 242.有效的字母异位词

题目链接:242.有效的字母异位词

解题思路

思路一(暴力解法)

先判断长度,如果长度不一样就输出false,一样的话我们将两个字符串变为两个char数组,再通过sort()函数按照ASCII码进行排序,然后用equal()函数比较两个数组是否一样。

class Solution {
    public boolean isAnagram(String s, String t) {
        if(s.length() != t.length()){
            return false;
        }
        char[] arr1 = s.toCharArray();
        char[] arr2 = t.toCharArray();
        Arrays.sort(arr1);
        Arrays.sort(arr2);
        return Arrays.equals(arr1, arr2);
    }
}

思路二(哈希表的应用—数组)

分析题目可知s 和 t 仅包含小写字母,则我们可以设置一个长度为26的数组,因为字符a到字符z的ASCII是26个连续的数值,所以字符a映射为下标0,相应的字符z映射为下标25。然后再对s字符串进行遍历,与之匹配的索引的值加一,结束之后,在对t字符串进行遍历,与之匹配的索引的值减一,然后对数组进行遍历,如果存在索引值不等于0的,输出false。

class Solution {
    public boolean isAnagram(String s, String t) {
        int[] record = new int[26];
        for(int i = 0; i < s.length(); i++){
            char c = s.charAt(i);
            record[c -'a']++;
        }
        for(int i = 0; i < t.length(); i++){
            char h = t.charAt(i);
            record[h -'a']--;
        }
        for(int count : record){
            if(count != 0){
                return false;
            }
        }
        return true;
    }
}

思路三(哈希表的应用—map)

初始版

我们可以将创建一个map,key为字符,value为字符的个数,然后对s字符串进行遍历,添加至map中,在对t的字符串进行遍历,如果不存在就添加进去,value设为-1,存在就对该key的value-1,如果key对应的value出现了-1则直接输出false,然后在对整个map的value进行求和如果不等于0则false反之ture

class Solution {
    public boolean isAnagram(String s, String t) {
        Map<Character, Integer> map = new HashMap<Character, Integer>();
        for(int i = 0; i < s.length(); i++){
            char c = s.charAt(i);
            map.put(c, map.getOrDefault(c, 0) + 1);
        }
        for(int i = 0; i < t.length(); i++){
            char h = t.charAt(i);
            map.put(h, map.getOrDefault(h, 0) - 1);
            if(map.get(h) < 0){
                return false;
            }
        }
        Integer totalCount = map.values().stream().mapToInt(Integer::intValue).sum();
        if(totalCount > 0){
            return false;
        }
        return true;
    }
}

改进版

我开始判断两个字符串的长度是否相同,如果不相同就一定不是字母异位词,而相同且两个字符串不是字母异位词,只有两种可能:

  1. 存在不相同的字母
  2. 相同字母的个数不相同

我们可以在遍历t字符串开始时判断如果字母的不存在或者字母对应value为0就输出false,不是则将对应的value-1。

class Solution {
    public boolean isAnagram(String s, String t) {
        if(s.length() != t.length()){
            return false;
        }
        Map<Character, Integer> map = new HashMap<Character, Integer>();
        for(int i = 0; i < s.length(); i++){
            char c = s.charAt(i);
            map.put(c, map.getOrDefault(c, 0) + 1);
        }
        for(int i = 0; i < t.length(); i++){
            char h = t.charAt(i);
            if(!map.containsKey(h) || map.get(h) == 0){
                return false;
            }
            map.put(h, map.get(h) - 1);
        }
        
        return true;
    }
}

LeetCode 349. 两个数组的交集

题目链接:349. 两个数组的交集

解题思路

这道题思路的不同主要在选取存放的哈希表的数据结构不同,分为一下三个:

  1. 数组:如果这道题目没有0 <= nums1[i], nums2[i] <= 1000这个条件,数组的长度就无法确定,会使得空间的浪费。
  2. HashSet:这道题目需要输出的数不重复,且不考虑顺序,符合set的性质
  3. HashMap:map的key,value能对需要对比的值进行查找。

解题思路: 如下图

思路一(哈希表的应用—数组)

class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        Set<Integer> res = new HashSet<Integer>();
        int[] hash = new int[1001];
        for(int i = 0; i < nums1.length; i++){
            hash[nums1[i]] = 1;
        }
        for(int i = 0; i < nums2.length; i++){
            if(hash[nums2[i]] == 1){
                res.add(nums2[i]);
            }
        }
        return res.stream().mapToInt(x -> x).toArray();
        //另一种输出方式
        // int[] ans = new int[res.size()];
        // int j = 0;
        // for(int i : res){
        //     ans[j] = i;
        //     j++;
        // }
        // return ans;
    }
}

思路二(哈希表的应用—set)

class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        Set<Integer> res = new HashSet<Integer>();
        Set<Integer> hash = new HashSet<Integer>();
        for(int i = 0; i < nums1.length; i++){
            hash.add(nums1[i]);
        }
        for(int i = 0; i < nums2.length; i++){
            if(hash.contains(nums2[i])){
                res.add(nums2[i]);
            }
        }
        return res.stream().mapToInt(x -> x).toArray();
        
        //另一种输出方式
        // int[] ans = new int[res.size()];
        // int j = 0;
        // for(int i : res){
        //     ans[j] = i;
        //     j++;
        // }
        // return ans;
    }
}

思路三(哈希表的应用—map)

class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        int n = 0;
        Set<Integer> res = new HashSet<Integer>();
        Map<Integer,Integer> map = new HashMap<Integer,Integer>();
        for(int i = 0; i < nums1.length; i++){
            map.put(nums1[i], map.getOrDefault(nums1[i], 1));
        }
        for(int i = 0; i < nums2.length; i++){
            if(map.containsKey(nums2[i])){
                res.add(nums2[i]);
            }
        }
        return res.stream().mapToInt(x -> x).toArray();
        
        //另一种输出方式
        // int[] ans = new int[res.size()];
        // int j = 0;
        // for(int i : res){
        //     ans[j] = i;
        //     j++;
        // }
        // return ans;
    }
}

LeetCode 202. 快乐数

题目链接:202. 快乐数

解题思路

思路一(哈希表的应用—set)

分析题目可知:
快乐数:
在这里插入图片描述
非快乐数:

在这里插入图片描述
上图出自:代码随想录算法训练营第六天|哈希表
代码的实现:

  1. 我要对数进行各位之间的平方的求和
  2. 求和的值是否等于一,
  3. 对求和的数在hashset中查找是否有相同的值,如果没有就加入到hashset中
  4. 结束上述循环的要么数值等于一,要么hashset出现相同值。
  5. 我们防止当n == 1s,没有加入循环,默认的boolean值为false时,再return时进行判断是否是n == 1。
初始版
class Solution {
    public boolean isHappy(int n) {
       boolean ans = false;
        int sum = 0;
        Set<Integer> res = new HashSet<Integer>();
        while(!res.contains(n) && n!=1) {
            res.add(n);
        	while(n > 0){
                sum = sum + (n % 10) * (n % 10);
                n = n / 10;
            }
            n = sum;
            sum = 0;
            if(n == 1){
                ans = true;
            }

        }
        return n == 1 ? true : ans;
    }
}
改进版
class Solution {
    public boolean isHappy(int n) {
        Set<Integer> res = new HashSet<Integer>();
        while(!res.contains(n) && n!=1) {
            res.add(n);
        	n = getNextNumber(n);
        }
        return n == 1;
    }
    private int getNextNumber(int n) {
        int sum = 0;
        while(n > 0){
            sum = sum + (n % 10) * (n % 10);
            n = n / 10;
        }
        return sum;
    }
}

LeetCode 1. 两数之和

题目链接:两数之和

解题思路

思路一(暴力解法)

class Solution {
    public int[] twoSum(int[] nums, int target) {
        int[] res = new int[2];
        for(int i = 0; i < nums.length; i++){
            for(int j = i + 1; j < nums.length; j++){
                if(nums[i] + nums[j] == target){
                    res[0] = i;
                    res[1] = j;
                }
            }
        }
        return res;
    }
}

思路二(哈希表的应用—map)

分析题目可知:
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
我们首先想到使用哈希表(一般哈希表都是用来快速判断一个元素是否出现集合里。

  1. 数组的大小是受限制的,而且如果元素很少,而哈希值太大会造成内存空间的浪费。
  2. set是一个集合,里面放的元素只能是一个key,而两数之和这道题目,不仅要判断y是否存在而且还要记录y的下标位置,因为要返回x 和 y的下标。所以set 也不能用。
  3. 而hashmap存在key和value,我们可以用key保留数组里的值,value保存值对应的索引,然后我们可以运用到containsKey函数去查找是否存在(target-num[i]),因为数组中会存在两个数之和等于target,我们去遍历数组,将第一个数加入进map,第二个数通过map函数去查找在map所在的value,然后输出当前位置和查询到的value。
class Solution {
    public int[] twoSum(int[] nums, int target) {
        int[] res = new int[2];
        Map<Integer,Integer> map = new HashMap<Integer,Integer>();
        for(int i = 0; i < nums.length; i++){
            if(map.containsKey(target - nums[i])){
                res[0] = map.get(target - nums[i]);
                res[1] = i; 
            }
            map.put(nums[i], i);
        }
        return res;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值