Day5 | 242有效的字母异位词&349两个数组的交集&202快乐数&1两数之和

71 阅读4分钟

有效的字母异位词 LeetCode 242

题目链接:LeetCode 242 - 简单

思路

第一想法是使用HashMap,但是后期发现使用数组更加方便。

HashMap:

java
class Solution {
    public boolean isAnagram(String s, String t) {
        if(s.length()!=t.length()){
            return false;
        }
        HashMap<Character,Integer> map = new HashMap<>();
        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 c = t.charAt(i);
            map.put(c,map.getOrDefault(c, 0) - 1);
            if(map.get(c)<0){
                return false;
            }
        }

        return true;
    }
}

总结

  1. map.getOrDefault(c, 0)如果HashMap中存在c元素的话,获取该value,否则设置为0。
  2. 使用数组进行所占的内存更少:
class Solution {
    public boolean isAnagram(String s, String t) {
        int[] c = new int[26];

        for(int i=0;i<s.length();i++){
            c[s.charAt(i)-'a']++;
        }

        for(int i=0;i<t.length();i++){
            c[t.charAt(i)-'a']--;
        }

        for(int recond:c){
            if(recond!=0){
                return false;
            }
        }
        return true;

    }
}

代码的优化问题-> 将

        for(int i=0;i<26;i++){
            if(c[i]!=0){
                return false;
            }
        }

优化为

        for(int recond:c){
            if(recond!=0){
                return false;
            }
        }

两个数组的交集 LeetCode 349

题目链接:LeetCode 349 - 简单

思路

第一想法是使用HashMap,但是在写代码的时候,发现HashMap使用的过程中,发现使用Set的方式会更好,因为题目中对于相同的数字效果一样。

HashSet:

java
class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        if(nums1 == null || nums1.length==0 || nums2 == null || nums2.length ==0){
            return new int[0];
        }

        HashSet<Integer> set = new HashSet<>();
        HashSet<Integer> resultSet = new HashSet<>();

        for(int num:nums1){
            set.add(num);
        }

        for(int num:nums2){
            if(set.contains(num)){
                resultSet.add(num);
            }
        }

        return resultSet.stream().mapToInt(x -> x).toArray();

    }
}

总结

  1. 使用HashMap的方法:
class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        if(nums1 == null || nums1.length ==0 || nums2 == null || nums2.length ==0){
            return new int[0];
        }
        HashMap<Integer,Integer> map = new HashMap<>();
        HashMap<Integer,Integer> resultMap = new HashMap<>();

        for(int num:nums1){
            map.put(num,map.getOrDefault(num,0)+1);
        }

        for(int num:nums2){
            if(map.containsKey(num)){
                resultMap.put(num,resultMap.getOrDefault(num,0)+1);
            }
        }
        return resultMap.keySet().stream().mapToInt(x -> x).toArray();
    }
}

与Set的差异为 1)set.contains(num)替换为map.containsKey(num) 2)将resultSet替换为resultMap.keySet()

  1. return resultSet.stream().mapToInt(x -> x).toArray();也可以替换为如下代码:
        int[] arr = new int[resSet.size()];
        int j = 0;
        for(int i : resSet){
            arr[j++] = i;
        }
        
        return arr;

快乐数 LeetCode 202

题目链接:LeetCode 202 - 简单

思路

看到题意理解,需要解决的是两点,①如何处理循环 ②如何处理每个数

HashSet:

java
class Solution {
    public boolean isHappy(int n) {
        HashSet<Integer> set = new HashSet<>();
        while( n!=1 && !set.contains(n)){
            set.add(n);
            n = getNextNumber(n);
        }
        return n == 1;
    }
    private int getNextNumber(int n){
        int res = 0;
        while( n > 0 ){
            int num = n % 10;
            res += num * num;
            n /= 10;
        }
        return res;
    }
}

总结

  1. 使用HashSet来解决循环问题,如果数字之前出现过,那么这个数就不是快乐数,并且退出循环
  2. 如何解决每个数,使用%和/

两数之和 LeetCode 1

哈希

题目链接:LeetCode 1 - 简单

思路

第一个想法就是两个for循环去查找

时间复杂度0(n^2):

java
class Solution {
    public int[] twoSum(int[] nums, int target) {
        int i=0,j=0;
        for(i=0;i<nums.length-1;i++){
            int targetNum = target - nums[i];
            for(j=i+1;j<nums.length;j++){
                if(nums[j]==targetNum){
                    int[] result = {i,j};
                    return result;
                }
            }
        }
        int[] result = {i,j};
        return result;
    }
}

总结

该题目可以使用HashMap来解决: ①使用HashMap可以使得两数相加在O(n)的时间复杂度内完成 ②使用HashMap而不是使用HashSet的原因是:可以使用key 和 value的组合,存储之前数组中数的下标。

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 targetNum = target - nums[i];
            if(map.containsKey(targetNum)){
                res[0] = map.get(targetNum);
                res[1] = i;
                return res;
            }
            map.put(nums[i],i);
        }
        return res;
    }
}

3.15次二刷:

class Solution {
    public int[] twoSum(int[] nums, int target) {
        HashMap<Integer,Integer> map = new HashMap<>();
        int index1 = 0;
        int index2 = 0;

        for(int i=0;i<nums.length;i++){
            map.put(nums[i],i);
        }

        for(int i=0;i<nums.length;i++){
            int num = target - nums[i];
            if(map.containsKey(num)){
                index1 = i;
                if(map.get(num)!=index1){
                    index2 = map.get(num);
                    break;
                }
            }
        }
        return new int[]{index1,index2};
    }
}

但是代码不够精炼,修改一下:

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

该两数之和算法采用的是哈希的做法。主要是通过在hashmap中查找是否存在num,如果找到,则返回结果,如果没有找到,则将当前的下标和值放入到hashmap中,继续下一次循环。

49. 字母异位词分组

哈希 hot100

class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        HashMap<String, List<String>> map = new HashMap<>();
        for (String s : strs) {
            char[] c = s.toCharArray();
            Arrays.sort(c);
            String key = new String(c);
            List<String> list = map.getOrDefault(key, new ArrayList<String>());
            list.add(s);
            map.put(key, list);
        }
        return new ArrayList<List<String>>(map.values());
    }
}

主要就是将单词sort后,异位的单词都一样,因此放到同一个hash的key中。

-> hash解决的问题 1、已知一个target,和另一个num1,求num2是否存在的问题 2、相同的字符串组成的String