力扣每日一题 2021/3

2021-03-01
3/1 区域和检索

难度 EASY 链接

比较简单,在初始化时记录累加和,sumRange返回累加和之差即可

3/2 二维区域和检索

难度 MEDI 链接

我的方法是计算matrix累加和,计算方法为sum_matrix[i][j]=sum_matrix[i-1][j]+sum_col[j]

然后返回矩阵差 = 大的-上面-左边+左上(重复减)

3/3 比特位计数

难度 MEDI 链接

好家伙,想到了DP,想到了位运算,然而本菜鸡一直在想x与x-1之间比特数的差别怎么计算,没想到最简单的方式是x与x去掉最左边的1之后的y之间,比特数差恒为1(去掉的那个1),这样就很简单了。

学到了位运算的技巧:x&(x-1)==0则x为2^n

3/4 俄罗斯套娃信封

难度 HARD 链接

算法课讲过,所以充分说明我全给忘了。。二维的最长子序列问题,可以以其中一维排序(相同时大的放前面)从而转化成一维,然后用O(n^2)的DP。不过看题解里有nlogn的,结合了贪心,有时间可以看看。

3/5 用栈实现队列

难度 EASY 链接

就没啥好说的,书上例子。因为C和python都没有栈就尝试了一下Java。用输入栈和输出栈,每次要输出时如果输出栈空就把输入栈依次出后push进输出栈,输出栈就成了FIFO。平摊分析一下操作的时间复杂度是O(4/2=2)

3/6 下一个更大元素 II

难度 MEDI 链接

自己想了一个办法,写完看题解才发现其实就是单调栈,不过我这样的实现似乎比栈更快…

这次官方题解讲得不好,贴一个讲得好的:动画讲解:单调栈

最主要的思想就是:如果元素是单调递减的(则他们的「下一个更大元素」相同)

3/7 分割回文串

难度 MEDI 链接

wtm直接懵逼,这是中等难度?直接看题解。

思路其实也不难,只不过被这种高复杂度的给吓到了

3/8 分割回文串 II

难度 HARD 链接

经典hard比medium简单。DP搞定,算法原题,O(n^2)复杂度。

3/9 删除字符串中的所有相邻重复项

难度 EASY 链接

简单,没啥好说的。用栈就行。另外似乎每日一题的规律是简单中等中等困难。

3/10 基本计算器

难度 HARD 链接

猜错了,今天是hard。。这道题难度不大,不过有一定的编程量。做完后发现答案利用栈的思路和方法好多了,代码量也少了很多。然后我才发现。。我多写了乘法的操作。。。下次看清题目。

3/11 基本计算器 II

难度 MEDI 链接

按照昨天的思路改了改,然后就拉了。。这道题因为没有括号,不需要这么麻烦。好的做法是根据数字前的符号压栈不同的值,乘除号只需要先弹栈,做运算后再压栈即可。

3/12 验证二叉树的前序序列化

难度 MEDI 链接

虽然是中等但是很简单,因为只考察二叉树是否正确,只需要计数判断即可。初始数字为1。规则为:

  1. 读入新数字,计数++
  2. 读入#,计数–

不合理的情况只有:

  1. #后有数字,反应为计数即为值≤0
  2. 数字后无#,即最终数字不为0
3/13 设计哈希集合

难度 EASY 链接

比较简单,没什么好说的,哈希算法用的是直接和1021(质数)取余。重复的用链表串起来。

3/14 设计哈希映射

难度 EASY 链接

怎么还是easy。和昨天的一样,int换成struct就行。

3/15 螺旋矩阵

难度 MEDI 链接

来点难的吧来点难的吧来点难的吧。

一层一层访问即可。注意上下重合和左右重合的处理。

3/16 螺旋矩阵 II

难度 MEDI 链接

来点难的吧来点难的吧来点难的吧。

和昨天差别不大,因为是正方形还简单点。先开数组,用index记录存哪个数。注意下标的取值。层数i从0到n/2,则每个边界从0到n-i*2。注意top和left。

写完才发现似乎都从0到n-i*2-1简单不少。。

3/17 不同的子序列

难度 HARD 链接

一道非常典型的dp。我的思路和题解差不多,转移方程如下:

if(s[i]==t[j])
	dp[i][j]=dp[i-1][j-1]+dp[i][j-1];
    //要么使其匹配,等于s[0:i-1]与t[0:j-1],要么不匹配,等于s[0:i]与t[0:j-1]
else
    dp[i][j]=dp[i-1][j];
    //无法匹配,等于s[0:i-1]与t[0:j]

看完评论后发现完全可以使用一维数组,dp[j]表示s[0:i]中出现t[0:j]的次数,转移方程为:

if(s[i]==t[j])
	dp[j]+=dp[j-1];
3/18 反转链表 II

难度 MEDI 链接

我的方法用了个栈,这样写方便很多。

空间复杂度为1的方法看题解。以及看到一点:一般机试不允许改节点值,那我的做法就不对了。

3/19 设计停车系统

难度 EASY 链接

浪费了人生中的一分钟。

3/20 逆波兰表达式求值

难度 MEDI 链接

后缀表达式的计算。没难度。

3/21 矩阵置零

难度 MEDI 链接

一开始没看懂啥意思,然后就看了题解。。思想在于如何节省空间,若矩阵某处为0,那最终这个矩阵所在行和列都会变为0,那么就可以提前把行首和列首记为0记录一下,这样就节省了额外新开记录数组的O(m+n)的空间。不过还需要考虑行首和列首本身是0导致最上和左侧最后也变为0的情况,需要用两个布尔标记一下。题解最后还有一个只用一个布尔变量的,感觉技巧性太强,意义不大。

3/22 位1的个数

难度 EASY 链接

最简单的方法是逐位检查,不过可以按照分治的思想先检查每2bits的,再4bits、8bits……

检查2bits的方法是n = (n & 0x55555555) + ((n >> 1) & 0x55555555);这样就把每2bits中1的数量记在里面。之后的做法就是右移+高位清零(依次与0x3333……、0x0F0F……、0x00FF00FF……做&操作)然后相加,实现计算结果并保存在4bits里,如此往复直到保存在32bits里,得到结果。

标准做法更nb一点,在仅剩4个8bits块时,与0x0101……相乘,这样按照乘法的原理,高8bits里实际上记录了四个块相加的结果,右移24即可。

3/23 扁平化嵌套列表迭代器

难度 MEDI 链接

这道题一开始看不懂,参考【负雪明烛】详解题意,梳理递归和迭代两种思路

迭代器的意思就是不断迭代访问元素,所以好的做法不是一开始就扁平化而是在访问过程中扁平化,也就是用栈。

3/24 132 模式

难度 MEDI 链接

从左到右的话要找到一个更大的再跟一个次大的,但是如果反过来就变成找一个更大的和一个更小的,方便了很多。但是具体怎么做我没想到很好的解决方案。答案用的是单调栈,挺有道理的,单调栈里存的是num2的备选,越接近底越大。这样每次遇到更大的数就利用这个单调栈判断能不能使num2变大,毕竟只要满足有num3的情况下num2越大越好即可。

另外还提到在实际应用中可能不会整个给出数组,可以看看复杂度O(nlogn)的方法3.

3/25 删除排序链表中的重复元素 II

难度 MEDI 链接

常规的链表题。因为好久没写链表出了一些低级错误。题目不难,多用变量标记即可。

3/26删除排序链表中的重复元素

难度 EASY 链接

先做2再做1,真有你的啊力扣。

改一下昨天代码就行。

3/27 旋转链表

难度 MEDI 链接

还是链表,依然不难。注意判断k(取模后)和n是否为0两种特殊情况即可。

3/28 二叉搜索树迭代器

难度 MEDI 链接

和上次那个迭代器差不多的意思,可以把入栈的操作放在hasNext(),因为这个好像是假设当需要调入的时候就会执行一次hasNext(),反正挺怪的。。。

3/29 颠倒二进制位

难度 EASY 链接

虽然知道应该有很nb的位运算,但是实在想不出来,只能老老实实按位取出数字。题解的分治方法太nb了,不是我等凡人想得出来的。

3/30 搜索二维矩阵

难度 MEDI 链接

做两次二分搜索就行,常规题目,练练手挺好的。

3/31 子集 II

难度 MEDI 链接

因为没想明白怎么高效地选择就看了题,其实很容易,对长度为n的数组,用n位二进制数就可以,1表示选择当前,0表示不选择。

这样就简单多了,先排序,然后对于选择了当前数、未选择下一个数、当前和下一个数相同这种情况,不添加其到最终结果。例如数组1,2,2,2对应二进制数1010(对应选择为0 1 0 1),在这种情况下,会随二进制数的累加在1100这种情况复现,故不用选择。

本文阅读量: