代码随想录算法训练营第六天 | 242、349、202、1

文章介绍了四道编程题目,包括判断两个字符串是否为字母异位词,找到两个数组的交集,判断一个数是否为快乐数以及寻找数组中两数之和等于目标值的索引。解题策略涉及哈希表、数组操作和循环检查。

242. 有效的字母异位词

题目描述

给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。
注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。
示例1:
输入:s="anagram",t="nagaram"s = "anagram", t = "nagaram"s="anagram",t="nagaram"
输出:truetruetrue
示例2:
输入:s="rat",t="car"s = "rat", t = "car"s="rat",t="car"
输出:falsefalsefalse

思路

因为两个字符串中均为小写字母,那么可以使用字母表作为记录的容器,即一个26元素的数组。可以在逻辑开始之前首先进行剪枝操作,当s和t的长度大小不同时,两个字符串是不可能成为异位词的,故而直接返回false。当二者长度相同时,可以在字母表中进行记录,s中存在的字母在字母表中记录+1,而t中存在的字母在字母表中记录-1,则二者为异位词当且仅当字母表中所有元素均为0.

解法

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

总结

本题为基本题型,把握好中间对于记录数组的增减即可。

349. 两个数组的交集

题目描述

给定两个数组 nums1 和 nums2 ,返回 它们的交集 。输出结果中的每个元素一定是唯一的。我们可以不考虑输出结果的顺序 。
示例1:
输入:nums1=[1,2,2,1],nums2=[2,2]nums1 = [1,2,2,1], nums2 = [2,2]nums1=[1,2,2,1],nums2=[2,2]
输出:[2][2][2]
示例2:
输入:nums1=[4,9,5],nums2=[9,4,9,8,4]nums1 = [4,9,5], nums2 = [9,4,9,8,4]nums1=[4,9,5],nums2=[9,4,9,8,4]
输出:[4,9][4,9][4,9]

思路

本题中首先要求返回交集,而后需要输出结果中元素唯一,那么可以想到使用Set来破题。
返回交集的功能可以通过一个set实现,而元素唯一可以通过另一个set实现,此题即可解。

解法

class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        Set<Integer> set1 = new HashSet<>();
        Set<Integer> set2 = new HashSet<>();
        for(int num1 : nums1){
            set1.add(num1);
        }
        for(int num2 : nums2){
            if(set1.contains(num2)){
                set2.add(num2);
            }
        }
        int []res = new int[set2.size()];
        int count = 0;
        for(int r : set2){
            res[count++] = r;
        }
        return res;
        
    }
}

总结

本题为基本题型,在看到交集,唯一,无需考虑顺序这样的形容词时,我们需要可以快速想到对set或map的使用。

202.快乐数

题目描述

编写一个算法来判断一个数 n 是不是快乐数。
「快乐数」 定义为:
对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
然后重复这个过程直到这个数变为 1,也可能是无限循环但始终变不到1。
如果这个过程 结果为 1,那么这个数就是快乐数。
如果 n 是 快乐数 就返回 true ;不是,则返回 false 。
示例1:
输入:n=19n = 19n=19
输出:truetruetrue
解释:
12+92=821^2 + 9^2 = 8212+92=82
82+22=688^2 + 2^2 = 6882+22=68
62+82=1006^2 + 8^2 = 10062+82=100
12+02+02=11^2 + 0^2 + 0^2 = 112+02+02=1
示例1:
输入:n=2n = 2n=2
输出:falsefalsefalse

思路

首先,在思考时可以发现本题可能存在三种情况:
1、最终得到了1
2、最终进入了循环
3、值越来越大但不会循环导致最后接近无穷
其中第三种情况是比较难处理和检测,因为我们不知道如何判断它最终是会继续变大还是会得到1。但其实,我们可以仔细想一下,每一位数的最大数字的下一位数是多少

digitsLargestNext
1981
299162
399981
4999981
1399999999999991053

由表格可知,对于3位数的数字,它不可能大于243,这意味着它要么被困在243以下的循环内,要么最终走到1。4位或4位以上的数字在每一步都会丢失一位,直到降到3位为止。所以我们知道,最坏的情况下,算法可能会在243以下的所有数字上进行循环,然后回到它已经到过的一个循环或者回到1。但它不会无限期地进行下去,所以我们排除了第三种可能。
那么此时,算法只需要两部分来解决了
1、计算数字n的下一个数字是什么
2、判断该数字是否进入了循环
第一部分很好解决,只需要数位分离求平方和即可。
而第二部分是否进入了循环则可以从两个角度进行理解,分别是:
1、一个元素是否已经出现过,通过这一思路思考则会使用哈希
2、一个链中是否存在环,通过这一思路则会使用隐式链表
从而,本题存在两种解法。

解法1

class Solution {
    public boolean isHappy(int n) {
        Set<Integer> set = new HashSet<>();
        while(n!=1 && !set.contains(n)){
            set.add(n);
            n = getNext(n);
        }
        return n == 1;
    }
    public int getNext(int n){
        int totalSum = 0;
        while(n>0){
            int d = n % 10;
            n = n/10;
            totalSum += d*d;
        }
        return totalSum;
    }
}

解法2

class Solution {
    public boolean isHappy(int n) {
        int slow = n;
        int fast = getNext(n);
        while(fast != 1 && slow !=fast){
            slow = getNext(slow);
            fast = getNext(getNext(fast));
        }
        return fast == 1;
    }
    public int getNext(int n){
        int totalSum = 0;
        while(n >0){
            int d = n%10;
            n = n /10;
            totalSum += d*d;
        }
        return totalSum;
    }
}

总结

本题最重要的是能够判断出猜测的第三种情况不存在,否则很难解出。
在两种解法中,最容易想到的还是解法1,是否陷入循环这一命题很容易就可以想到应用哈希来判断是否重复。
但解法2也能够拓宽一下思路叭。

1.两数之和

题目描述

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
示例1:
输入:nums=[2,7,11,15],target=9nums = [2,7,11,15], target = 9nums=[2,7,11,15],target=9
输出:[0,1][0,1][0,1]
示例2:
输入:nums=[3,2,4],target=6nums = [3,2,4], target = 6nums=[3,2,4],target=6
输出:[1,2][1,2][1,2]
示例3:
输入:nums=[3,3],target=6nums = [3,3], target = 6nums=[3,3],target=6
输出:[0,1][0,1][0,1]

思路

本题是典型的哈希题目,使用一个map即可破题。

解法

class Solution {
    public int[] twoSum(int[] nums, int target) {
        HashMap<Integer,Integer> map = new HashMap<>();
        int[] res = new int[2];
        for(int i=0;i<nums.length;i++){
            int cur = target-nums[i];
            if(map.containsKey(cur)){
                res[0] = i;
                res[1] = map.get(cur);
                break;
            }
            map.put(nums[i],i);
        }
        return res;
    }
}

总结

本题是典型的哈希题,需要做的就是能够快速判断出本题应该使用哈希。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值