LeetCode-18
1668. 最大重复子字符串
1 | class Solution { |
笨方法,从右向左找,适当回溯
754. 到达终点数字
解法1
1 | class Solution { |
这道题直接暴力搜索是不可行的,算法成为$ O( 2^{ target } ) $ 级别
考虑到只求步数,负数target可以转化成正数处理
首先计算 $ sum = 1 + 2 + 3 + … + i + … + n <= target $, 如果 $ sum==target $,则n就是步数
否则对sum进行调整,记 $ diff = target-sum <= n $ (一定小于n+1),所以需要先减小sum,再加上几个数,使得新的sum等于target
情况一,第i步改为向左,再加上n+1, 也就是 $ sum - 2i + n+1 $,调整前后的差为 $ delta = n + 1 -2i $, $ i = 1,2,3,…,n; delta = n-1, n-3, n-5 … $。这种情况对于diff奇数n偶数
,或diff偶数n奇数
的情况适用,总计步数n+1
情况二,第i步改为向左,再加上n+1和n+2,也就是 $ sum - 2i + n+1 + n+2 $,调整前后的差为 $ delta = 2(n-i) + 3 $, $ i = 1,2,3,…,n; delta = 3, 5, 7, 9, … $。这种情况对于diff奇数且diff >= 3
的情况适用,总计步数n+2
情况三,减去n+1
,加上n+2
,显然使用于diff=1
的情况,总计步数n+2
,可以和情况二合并
情况四,以上没有覆盖到的情况,举个例子可知,总计步数n+3
解法2
1 | class Solution { |
计算 $ sum=1+2+3+…+n >= target $
情况一:如果 $ diff = sum-target <= n $ 是偶数,则步数就是n。 由于diff <= n,所以可以让第i步变成向左,即 $ sum - 2i, i=0,1,2,3,…,n+1 $,则刚好可以变成target
其他情况:如果diff是奇数,则继续在sum的基础上加n,直到diff为偶数
方法3
1 | class Solution { |
根据方法1,调整的步数最多3步,进一步分析,当diff为奇数时,sum加几个数可以变成偶数,根据公式 $$ sum = n(n+1)/2 $$
可知:
n偶数,sum偶数,n+1奇数,sum=sum+n+1
后sum变奇数
$$ n = 4i, sum=2i(2i+1) $$
n奇数,sum奇数,n+1偶数,n+2奇数,sum=sum+n+1+n+2
后sum变偶数
$$ n = 4i+1, sum=(4i+1)(2i+1) $$
n偶数,sum奇数,n+1奇数,sum=sum+n+1
后sum变偶数
$$ n = 4i+2, sum=(2i+1)(4i+3) $$
n奇数,sum偶数,n+1偶数,n+2奇数sum=sum+n+1+n+2
后sum变奇数
$$ n = 4i+3, sum=(4i+3)(2i+2) $$由于diff为奇数,则sum为奇数时要变成偶数,否则变成奇数
整理上面的讨论,可知调整的步数为n%2+1
,总步数为n+n%2+1
1106. 解析布尔表达式
1 | class Solution { |
就是写一个计算器,难点在于n元运算,需要在数值栈中保存括号,以判断每个操作作用于那些值
1678. 设计 Goal 解析器
1 | class Solution { |
816. 模糊坐标
1 | class Solution { |
1684. 统计一致字符串的数目
1 | class Solution { |
位运算
1 | class Solution { |
题中说明了 allowed只包含26个字母,所以用一个int就可以表示字符是否存在
764. 最大加号标志
前缀和
1 | class Solution { |
刚开始想用dp,但是想法不对,试了7.8次,最后想到正确的方法
x, y记录点(i, j) 右测/下方第一个0的坐标,minx记录左方第一个0的坐标,miny记录上方第一个0的位置
mat用来保存这个矩阵
加号的阶数为(i, j)坐标到上下左右四个方向上最近的0的距离的最小值
要注意特殊值的处理,右侧/下方没有0,则记其坐标为n
,上方/左侧没有0记为-1
一直以为只有把某一侧的数全都加起来才算前缀和
只要是把每个位置之前的一维线段或二维矩形预先存储,就叫做前缀和/积分图
大佬的解法
1 | class Solution { |
其实仔细一看,和我是一样的,一个一维for两个二维for,但是很短
dp存的是到最近的一个0的长度
优化空间
1 | class Solution { |
参考大佬的方法,把我的思路优化成只用一个二维数组
这里要注意mat初始化为n,如果初始化为1的话后面没办法找最小值。
462. 最小操作次数使数组元素相等 II
前缀和
1 | class Solution { |
先排序,假设第i个数是能使总体调整数最小的数,那么总的调整次数为
$$ i \times nums_i - \sum_{ j=0 }^{ j=i-1 }(nums_i) + \sum_{ j=i+1 }^{ j=n-1 }(nums_j) - (n - i -1) \times nums_i $$
$$ i = 0,1,…,n-1 $$
并使用前缀和优化
找他的最小值即可
数学方法
1 | class Solution { |
排序后,中位数之一刚好就是所求元素
假设 $ a_i a_j; i+j=len-1 $ 为两个待调整元素
$ h $ 为最终调整后的数,那么 $$ h = a_j - d_j = d_i - a_i $$
也就是 $$ a_j - a_i = d_j + d_i $$
对于关于中心对称的数,不管要调整成他们中间的哪一个数,调整的步数之和总是 $ a_j - a_i $
- 所以根本不需要知道最终调整成哪个数,只要计算对称位置的两个数的差值之和即可
1 | class Solution { |
不排序找到第len/2小的数
1 | class Solution { |
- 自己实现partition
1 | class Solution { |
太慢了。。。
- 去掉swap
1 | class Solution { |
470. 用 Rand7() 实现 Rand10()
1 | class Solution { |
满身反骨
202. 快乐数
1 | class Solution { |
大家都有相同的循环节
快慢指针
1 | class Solution { |
1 | class Solution { |
790. 多米诺和托米诺平铺
1 | class Solution { |
没通过,思路不对,算阶乘溢出,找出所有组合的代价也太大
在这个地方我犯了一个错误,就是认为 $ \frac{a}{b} \quad mod\quad c = \frac{a\quad mod\quad c}{b\quad mod\quad c} $
正确的关系是, $ \frac{a}{b}\quad mod\quad c = \frac{a\quad mod\quad (b \cdot c)}{b} $ ,证明:
$ \frac{a}{b}\quad mod\quad c = k $
$ \frac{a}{b} = x \cdot c + k $
$ a = b \cdot x \cdot c + b \cdot k $
$ a\quad mod\quad (b \cdot c) = b \cdot k $
$ a\quad mod\quad (b \cdot c) / b = k $
$ \frac{a}{b}\quad mod\quad c = \frac{a\quad mod\quad (b \cdot c)}{b} $
$ a^n \quad mod \quad c = (a \cdot a^{n-1}) \quad mod \quad c = ((a \quad mod \quad c) \cdot (a^{n-1} \quad mod \quad c)) \quad mod \quad c$
dp
1 |
|
快速幂
1 |
|
791. 自定义字符串排序
1 | class Solution { |