Leetcode 每日一题和每日一题的下一题刷题笔记 3/30

429 阅读5分钟

Leetcode 每日一题和每日一题的下一题刷题笔记 3/30

写在前面

这是我参与更文挑战的第3天,活动详情查看:更文挑战

快要毕业了,才发现自己被面试里的算法题吊起来锤。没办法只能以零基础的身份和同窗们共同加入了力扣刷题大军。我的同学们都非常厉害,他们平时只是谦虚,口头上说着自己不会,而我是真的不会。。。乘掘金鼓励新人每天写博客,我也凑个热闹,记录一下每天刷的前两道题,这两道题我精做。我打算每天刷五道题,其他的题目嘛,也只能强行背套路了,就不发在博客里了。

本人真的只是一个菜鸡,解题思路什么的就不要从我这里参考了,编码习惯也需要改进,各位如果想找刷题高手请教问题我觉得去找 宫水三叶的刷题日记 这位大佬比较好。我在把题目做出来之前尽量不去看题解,以免和大佬的内容撞车。

另外我也希望有得闲的大佬提供一些更高明的解题思路给我,欢迎讨论哈!

好了废话不多说开始第三天的前两道题吧!

2021.6.3 每日一题

525. 连续数组

这个月都是前缀和,那这个题应该可以往上面套。前缀和此时等于从最开始到现在一共看到了多少个 1。然后两个前缀和作差是这一段子数组中 1 的数量。只要 1 的数量占子数组长度的一半,这个子数组里面 01 就是一样多的。不过我这么直接写,就又和昨天一样,是两层循环,肯定要超时了。于是昨天的技巧又派上用场了,肯定要用哈希表。但是现在只统计了 1 的数量,0 的数量没被统计进来。哈希表里面存的键不能重复,然后出现重复,才能往前找,这里直接把前缀和当键是得不到重复值的。需要构造一个合适的东西当值往哈希表里面去存。比如说 10 数量之差。假设某个位置 i 对应的前缀和是 sum[i],那么从最开始到这里,1 的数量是 sum[i]0 的数量是 i - sum[i],两者之差是 2 * sum[i] - i,这个肯定就有重复的了。这样,在一次遍历中,把每个位置的前缀和算出来,再把 10 数量之差算出来,如果之前出现过相同的数量之差,证明前面那个位置到此处之间的子数组里面 01 一样多,没出现,就登记。哈希表里面键是数量之差(不是数量之差的绝对值),值是原本数组的元素编号。01 两者之差如果是迭代计算的话,遇到 1 差加一,遇到 0 差减一。就没必要按着前缀和和编号那样算了,不然哈希表省出来一次循环又白省。

接下来撸码,注意和昨天一样最开始是从-1计数,这样能找到从0开始的开头。


class Solution {
public:
    int findMaxLength(vector<int>& nums) {
        int maxLength = 0;
        unordered_map<int, int> difference_and_position;
        int difference = 0;
        difference_and_position[difference] = -1;
        int n = nums.size();
        for (int i = 0; i < n; i++) {
            int num = nums[i];
            if (num == 1) {
                difference = difference + 1;
            } else {
                difference = difference - 1;
            }
            if (difference_and_position.count(difference)) {
                int previous_index = difference_and_position[difference];
                maxLength = max(maxLength, i - previous_index);
            } else {
                difference_and_position[difference] = i;
            }
        }
        return maxLength;
    }
};

今天过的比较顺畅一些,希望之后也能这么顺畅。

image.png

看到官方题解,发现自己写的和题解很像,厉害了。

2021.6.3 每日一题下面的题

摸奖时间,希望来个简单的

368. 最大整除子集

这道题,估计是动态规划,我的感觉应该差不了太多,只要把下标混在一起然后我不好分开的基本上就是动态规划。为了方便只找因数或者只找倍数,要先来个排序,这里用升序好了。

动态规划我有点眼高手低,先确定状态和状态转移方程。状态是当前这个数对应的子集大小。因为是升序,现在这个数是子集里最大的那个。状态转移是当前这个数之前的某个位置上的数是现在这个数的因数,这样计算子集大小可以直接从因数对应的子集大小开始计算。举个例子,假如现在这个数是24,升序排序后前面有个数是 1212 对应的子集里面有 1, 3, 6。这样24可以直接凑到12的这个子集里,形成 {1, 3, 6, 12, 24} 这样的子集。最开始状态里存的子集大小是1,就是只有自己一个元素这样。

撸码开始,我写的不够简洁,一直想直接把最大子集的长度找出来,结果没看到题目要的是最大子集本身。。。有毒。。。改来改去最后还是参考了题解,既然这样就不粘贴代码了,大家去看官方题解吧。

要注意的点是最大长度就是1的情况,和其他情况分开的话,代码还简单点。。。然后一定把题目看清,还有返回类型提示我我都没反应过来

image.png

小结

哈希表键和值存什么,需要怎么构造。

动态规划把题目看清楚,状态和初始化想明白。

参考链接

写到这里发现今天没参考什么资料,可能是题型和之前比较相像。