Bootstrap

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

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

242.有效的字母异位词

242. 有效的字母异位词 - 力扣(LeetCode)

给定两个字符串 st ,编写一个函数来判断 t 是否是 s

字母异位词

示例 1:

输入: s = "anagram", t = "nagaram"
输出: true

示例 2:

输入: s = "rat", t = "car"
输出: false

提示:

  • 1 <= s.length, t.length <= 5 * 104
  • st 仅包含小写字母

进阶: 如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况?

思想

  • 由于英文单词只有26个字母,所以可以声明一个具有26个元素的数组用来存储每个字母在第一个单词中出现的次数。然后再用记录次数的数组减去在第二个字符串相同字母出现的次数。看是否数组中的元素为零,如果是0则是有效的字母异位。
  • 在这里不需要知道每个字母具体的ASCII码的值,因为在俩个字母相减的时候,会自动转换为ASCII码相减,比如a-a=0,b-a=1。
class Solution {
    public boolean isAnagram(String s, String t) {
        int[] count = new int[26];
        if(s.length() != t.length()){
            return false;
        }
        for(int i = 0;i < s.length();i++){
            count[s.charAt(i)-'a']++;
        }
        for(int i = 0;i < t.length();i++){
            count[t.charAt(i)-'a']--;
        }
        for(int i = 0;i < s.length();i++){
            if(count[s.charAt(i)-'a'] != 0){
                return false;
            }
        }
        return true;
    }
}

349.两个数组的交集

349. 两个数组的交集 - 力扣(LeetCode)

给定两个数组 nums1nums2 ,返回它们的交集

。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序

示例 1:

输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2]

示例 2:

输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[9,4]
解释:[4,9] 也是可通过的

提示:

  • 1 <= nums1.length, nums2.length <= 1000
  • 0 <= nums1[i], nums2[i] <= 1000

思想1:使用HashSet求解,会自动帮我们把重复的元素去掉。将第一个数组存放在哈希表中,然后查看第二个数组中是否有元素在哈希表中出现,如果出现就加入到存储交集的哈希表中。

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> hashSet = new HashSet<>();
        Set<Integer> resSet = new HashSet<>();
        for(int num : nums1){
            hashSet.add(num);
        }
        for(int num : nums2){
            if(hashSet.contains(num)){
                resSet.add(num);
            }
        }
        int[] nums = new int[resSet.size()];
        int i = 0;
        for(int num : resSet){
            nums[i++] = num;
        }
        return nums;
    }
}

思想2:由于题目更新,数组大小和数量有限,所以可以使用数组求解。比如说:数组中有1000就用nums1[1000]存储其出现的次数,只要nums1[1000]和nums2[1000]都大于零,那么就是交集,就把他加到新的数组中,如何添加呢?直接把元素值不为零的下标加入即可。

class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        int[] has1 = new int[1001];
        int[] has2 = new int[1001];
        for(int i : nums1){
            has1[i]++;
        }
        for(int i : nums2){
            has2[i]++;
        }
        List<Integer> resList = new ArrayList<>();
        for(int i = 0;i < 1001;i++){
            if(has1[i] > 0 && has2[i] > 0){
                resList.add(i);
            }
        }
        //转换为数组
        int[] nums = new int[resList.size()];
        int i = 0;
        for(int num : resList){
            nums[i++] = num;
        }
        return nums;
    }
}

注意:声明数组时,一定要写中括号[].

202. 快乐数

202. 快乐数 - 力扣(LeetCode)

编写一个算法来判断一个数 n 是不是快乐数。

「快乐数」 定义为:

  • 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
  • 然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
  • 如果这个过程 结果为 1,那么这个数就是快乐数。

如果 n快乐数 就返回 true ;不是,则返回 false

示例 1:

输入:n = 19
输出:true
解释:
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1

示例 2:

输入:n = 2
输出:false

思想:注意一点,根据快乐数的计算规则,在计算过程中,如果他不是快乐数,那么一定会出现重复的数字。那么如果出现了重复的数字我们就能判断他不是快乐数。因为,你再次出现了,表示后续的数字序列会重复出现。
注意:一次只判断一个数字。

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

1. 两数之和

1. 两数之和 - 力扣(LeetCode)

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。

你可以按任意顺序返回答案。

示例 1:

输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

示例 2:

输入:nums = [3,2,4], target = 6
输出:[1,2]

示例 3:

输入:nums = [3,3], target = 6
输出:[0,1]

思想

  • 也就是俩俩元素组合求和,看能不能找到目标值。只要我加过了就不用再相加了,那我就每次多一个数,多的一个数肯定没有和之前遍历过的元素相加过。
  • 这里因为我们要寻找自己的目标值(假如1+2=3,已知1,那么2就是目标值)是否存在,又要记录其下标,所以用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] = i;
                res[1] = map.get(temp);
                break;
            }else{
                map.put(nums[i],i);
            }
        }
        return res;
    }
}