代码随想录算法训练营第五天| LeetCode242.有效的字母异位词、349. 两个数组的交集、202. 快乐数、1. 两数之和
LeetCode242.有效的字母异位词
● 今日学习的文章链接和视频链接
题目链接
● 自己看到题目的第一想法
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. 两个数组的交集
● 今日学习的文章链接和视频链接
题目链接
● 自己看到题目的第一想法
这道题目数组的长度和大小都限定在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. 快乐数
● 今日学习的文章链接和视频链接
题目链接
力扣(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. 两数之和
● 今日学习的文章链接和视频链接
题目链接
● 自己看到题目的第一想法
做过很多遍,但是几乎都是直接把思路记录下来了。这个思路还比较巧妙,每次判断都是判断当前数的“余数在不在集合中”,不在的话说明是第一次加入这个数,在的话说明已经把它的余数加到集合中了。我们已经找到了目标,可以直接返回了。
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