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

发布时间 2023-12-19 01:14:27作者: xiaoni2023

LeetCode242.有效的字母异位词   

● 今日学习的文章链接和视频链接

代码随想录 (programmercarl.com)

题目链接

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

● 自己看到题目的第一想法

 public boolean anagram(String s, String t) {
        int[] dic = new int[26];
        if (s.length() != t.length()) {
            return false;
        }
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            dic[c - 'a']++;
            char c1 = t.charAt(i);
            dic[c1 - 'a']--;
        }
        for (int i = 0; i < 26; i++) {
            if (dic[i] != 0) {
                return false;
            }
        }
        return true;
  }

 

● 看完代码随想录之后的想法

判断元素有没有出现在集合中的时候就要想到用哈希表

要用到哈希表的问题,第一个就可以想想能不能用数组,如果可以用数组那么效率是最快的,如果要用set或者map,那么还要做哈希运算,并且存储结构也是比较复杂的

 

● 自己实现过程中遇到哪些困难

● 今日收获,记录一下自己的学习时长

1h

 

LeetCode349. 两个数组的交集

● 今日学习的文章链接和视频链接

 代码随想录 (programmercarl.com)

题目链接

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

● 自己看到题目的第一想法

这道题目数组的长度和大小都限定在1000以内了,所以我想可以直接用两个数组存一下有哪些数字出现了,然后再对比一下这两个数组就行了

    public int[] intersection(int[] nums1, int[] nums2) {
        byte[] dic1 = new byte[1100];
        byte[] dic2 = new byte[1100];
        for (int i : nums1) {
            dic1[i] = 1;
        }
        for (int i : nums2) {
            dic2[i] = 1;
        }
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i <= 1000; i++) {
            if (dic1[i] == 1 && dic2[i] == 1) {
                list.add(i);
            }
        }
        return list.stream().mapToInt(Integer::intValue).toArray();
    }

● 看完代码随想录之后的想法

首先不用两个数组,一个数组存出现的数,另一个数组直接循环遍历就可以,然后用set来存储结果自然可以避免结果集中出现重复的值。

    public int[] intersection(int[] nums1, int[] nums2) {
        byte[] dic1 = new byte[1100];
        Set<Integer> set = new HashSet<>();
        for (int i : nums1) {
            dic1[i] = 1;
        }
        for (int i : nums2) {
            if (dic1[i] == 1) {
                set.add(i);
            }
        }
        return set.stream().mapToInt(Integer::intValue).toArray();
    }

并且对于输入数据比较大的情况,用数组来作为哈希表记录显然是不太合适了,那么我们最好用集合来存储,鉴于这个知道元素的出现与否就可以,那么我们用存储单列元素的set就可以,结果集也用set来存储,可以去重

    public int[] intersection2(int[] nums1, int[] nums2) {
        Set<Integer> set = new HashSet<>();
        for (int i : nums1) {
            set.add(i);
        }
        Set<Integer> res = new HashSet<>();
        for (int i : nums2) {
            if (set.contains(i)) {
                res.add(i);
            }
        }
        return res.stream().mapToInt(x -> x).toArray();
    }

● 自己实现过程中遇到哪些困难

在找set是不是有直接去重的api,结果发现没有

然后Java和c++也不一样,没有直接把数组编程set的api,还是要通过朴素的遍历方式才可以

● 今日收获,记录一下自己的学习时长

1h

 

LeetCode202. 快乐数

● 今日学习的文章链接和视频链接

 代码随想录 (programmercarl.com)

题目链接

 力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

● 自己看到题目的第一想法

没想明白怎么跳出循环,也即如果不是快了数要怎么判断,所以提交之后果然超时了

public boolean isHappy(int n) {
        int sum = getSum(n);
        while (true) {
            if (sum == 1) {
                return true;
            } else {
                sum = getSum(sum);
            }
        }
    }

    private int getSum(int n) {
        int sum = 0;
        while (n != 0) {
            sum += (n % 10) * (n % 10);
            n = n / 10;
        }
        return sum;
    }

● 看完代码随想录之后的想法

原来如此,如果sum出现过一次后又出现了,那说明之前的过程又要再来一遍了,所以会陷入死循环

public boolean isHappy(int n) {
        //只要记录下sum,如果重复出现了,说明肯定会进入死循环
        Set<Integer> set = new HashSet<>();
        int sum = getSum(n);
        while (sum != 1) {
            if (set.contains(sum)) {
                return false;//set包含这个值就直接返回
            } else {
                set.add(sum);//set不包含这个sum值就加入进来
            }
            sum = getSum(sum);
        }
        return true;
    }

● 自己实现过程中遇到哪些困难

● 今日收获,记录一下自己的学习时长

1h

 

LeetCode1. 两数之和   

● 今日学习的文章链接和视频链接

 代码随想录 (programmercarl.com)

题目链接

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

● 自己看到题目的第一想法

做过很多遍,但是几乎都是直接把思路记录下来了。这个思路还比较巧妙,每次判断都是判断当前数的“余数在不在集合中”,不在的话说明是第一次加入这个数,在的话说明已经把它的余数加到集合中了。我们已经找到了目标,可以直接返回了。

    public int[] twoSum(int[] nums, int target) {
        Map<Integer, Integer> map = new HashMap<>();
        int[] res = new int[2];
        for (int i = 0; i < nums.length; i++) {
            if (!map.containsKey(target - nums[i])) {
                map.put(nums[i], i);
            } else {
                res[0] = map.get(target - nums[i]);//取出余数的下标
                res[1] = i;//当前数的下标
            }
        }
        return res;
    }

● 看完代码随想录之后的想法

首先是为什么要用哈希表,因为我们实际是要在遍历每一个元素的过程中,寻找到每个元素的余数是否出现过,既然要判断元素是否出现过,所以要用集合。

其次是用哪种哈希表,这里我们除了要判断元素是否出现过之外,还要返回下标,所以要提前把这个下标存储起来

那map到底怎么用呢,因为我们要判断元素余数有没有出现过,所以就可以在遍历的时候把没配对好的数先存起来,等到找到和它配对的余数了,再通过key把下标取出来

另外还有一点值得注意的是,map的key存的是数组中的值,value存储的则是数组的下标,因为我们要快速判断数组中的元素是否存在,所以要用key值来存储,这样查找的时间复杂度低,而用value存的话后果是什么?map不允许key值重复,但是允许value值重复的,当一个map寻找一个value时会遍历hashmap的所有条目。

● 自己实现过程中遇到哪些困难

● 今日收获,记录一下自己的学习时长

1h