代码随想录第六天 (哈希) 有效的字母异位词 两个数组的交集 快乐数 两数之和

一、有效的字母异位词

力扣第242题

题目描述:

给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。

注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。

示例1:

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

示例2:

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

解题思路:

题目中只出现小写字母,所以可以创建一个整型数组record[26],数组下标表示字母(例:0 代表a,可以通过 'a' - 'a' 得到,1 代表 b, 可以通过 'b' - 'a' 得到),遍历 s ,数组的内容记录 s 中字母出现的次数,然后遍历 t ,减去 t 中字母出现的次数,最后遍历 record 数组,若数组内容都为零,则满足条件,返回true,否则,返回 false

因为数据太小,用数组模拟哈希即可,可以不用 set 和 map 

代码如下:

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']++;     // 并不需要记住字符a的ASCII,只要求出一个相对数值就可以了
        }

        for (int i = 0; i < t.length(); i++) {
            record[t.charAt(i) - 'a']--;
        }
        
        for (int count: record) {
            if (count != 0) {               // record数组如果有的元素不为零0,说明字符串s和t 一定是谁多了字符或者谁少了字符。
                return false;
            }
        }
        return true;                        // record数组所有元素都为零0,说明字符串s和t是字母异位词
    }
}

时间复杂度:O(m + n)  m 和 n 是 s 和 t 的长度

空间复杂度:O(1);

HashMap版本:

class Solution {
    public boolean isAnagram(String s, String t) {
        HashMap<Character,Integer> map = new HashMap<>();
        for(int i = 0; i < s.length(); i++) {
            int count = map.getOrDefault(s.charAt(i), 0);
            map.put(s.charAt(i), ++count);
        }

        for(int i = 0; i < t.length(); i++) {
            int count = map.getOrDefault(t.charAt(i), 0);
            if(count == 0) {
                return false;
            }
            count--;
            if(count == 0) {
                map.remove(t.charAt(i));
            }else {
                map.put(t.charAt(i), count);
            }
        }
        if(map.isEmpty()) {
            return true;
        }
        return false;
    }
}

时间复杂度:O(m + n)  m 和 n 是 s 和 t 的长度

空间复杂度:O(1);  

二、两个数组的交集

力扣第349题:

题目描述:给定两个数组 nums1 和 nums2 ,返回 它们的 交集。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。

示例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] 也是可通过的

解题思路:

创建一个哈希表 set ,遍历nums1,将nums1中的所有数字加入到 set 表中,然后创建第二个哈希表 res ,遍历nums2,如果nums2 中的数字出现在 set 表中,则将其加入到 res 中,最后将 res 转为数组,返回结果。

tips:

用数组模拟哈希比 HashSet 快很多,因为 HashSet 对每个元素都会进行哈希运算,所以当所统计的元素可以用数组下标来表示的话,用数组模拟哈希更快一些

代码如下:

class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        Set<Integer> set = new HashSet<>();
        Set<Integer> res = new HashSet<>();
        for(int num : nums1) {
            set.add(num);
        }
        for(int num : nums2) {
            if(set.contains(num)) {
                res.add(num);
            }
        }
        int[] ans = new int[res.size()];
        int k = 0;
        for(int num : res) {
            ans[k++] = num;
		}
        return ans;
    }
}

时间复杂度:O(m + n)   遍历两个数组花的时间

空间复杂度:O(n)  res 表的空间小于 set,所以空间复杂度主要取决于set

三、快乐数

力扣第202题:

题目描述:

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

「快乐数」 定义为:

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

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

示例:

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

解题思路:

创建一个 set 集合,将 n 加入集合,将  n 每一位上的数字的平方和用 count 记录,判断 count 是否在 set 集合中,如果存在,说明 count  处于循环中,判断 count 是否为1,若不存在,说明 count 没有进入循环,或者说还没完成第一次循环,则将 count 加入 set 集合里,重复上述过程,直到出现答案。

代码如下:

class Solution {
    public boolean isHappy(int n) {
        Set<Integer> set = new HashSet<>();
        set.add(n);
        int count = 0; 
        while(true) {
            while(n != 0) {
                int rem = n % 10;
                n = n / 10;
                count += rem * rem;
            }
            if(set.contains(count)) {
                return count == 1;
            }else {
                set.add(count);
            }
            n = count;
            count = 0;
        }
    } 
}

时间复杂度:o(logn)

空间复杂度:o(logn)

四、两数之和

力扣第1题:

题目描述:

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

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

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

示例:

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

解题思路:

一次遍历解决问题,创建 map 映射,遍历数组 nums ,将数组元素以 数值-下标 的键值对形式存储在 map 中,并且判断 target -与当前遍历的元素值的差是否存在 map 中,如果存在,就是我们要查找的两个值,返回下标即可。

代码如下:

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

时间复杂度:O(n)

空间复杂度:O(n)

  • 9
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值