lc算法题:动态规划dp

  1. 优美的排列
    假设有从 1 到 N 的 N 个整数,如果从这 N 个数字中成功构造出一个数组,使得数组的第 i 位 (1 <= i <= N) 满足如下两个条件中的一个,我们就称这个数组为一个优美的排列。条件:

第 i 位的数字能被 i 整除
i 能被第 i 位上的数字整除
现在给定一个整数 N,请问可以构造多少个优美的排列?

法1:状态dp

  1. 出界的路径数
  2. 给你一个大小为 m x n 的网格和一个球。球的起始坐标为 [startRow, startColumn] 。你可以将球移到在四个方向上相邻的单元格内(可以穿过网格边界到达网格之外)。你 最多 可以移动 maxMove 次球。

给你五个整数 m、n、maxMove、startRow 以及 startColumn ,找出并返回可以将球移出边界的路径数量。

法1:路径dp

  1. 学生出勤记录 II
    可以用字符串表示一个学生的出勤记录,其中的每个字符用来标记当天的出勤情况(缺勤、迟到、到场)。记录中只含下面三种字符:
    ‘A’:Absent,缺勤
    ‘L’:Late,迟到
    ‘P’:Present,到场
    如果学生能够 同时 满足下面两个条件,则可以获得出勤奖励:

按 总出勤 计,学生缺勤(‘A’)严格 少于两天。
学生 不会 存在 连续 3 天或 连续 3 天以上的迟到(‘L’)记录。
给你一个整数 n ,表示出勤记录的长度(次数)。请你返回记录长度为 n 时,可能获得出勤奖励的记录情况 数量 。答案可能很大,所以返回对 109 + 7 取余 的结果。

## 规定时间(或次数)下到达终点的最小花费
lc787. K 站中转内最便宜的航班
lc1928. 规定时间内到达终点的最小花费
法:dfs转动规

650. 只有两个键的键盘
最初记事本上只有一个字符 ‘A’ 。你每次可以对这个记事本进行两种操作:
Copy All(复制全部):复制这个记事本中的所有字符(不允许仅复制部分字符)。
Paste(粘贴):粘贴 上一次 复制的字符。
给你一个数字 n ,你需要使用最少的操作次数,在记事本上输出 恰好 n 个 ‘A’ 。返回能够打印出 n 个 ‘A’ 的最少操作次数。

629. K个逆序对数组
给出两个整数 n 和 k,找出所有包含从 1 到 n 的数字,且恰好拥有 k 个逆序对的不同的数组的个数。
逆序对的定义如下:对于数组的第i个和第 j个元素,如果满i < j且 a[i] > a[j],则其为一个逆序对;否则不是。
由于答案可能很大,只需要返回 答案 mod 109 + 7 的值。

375. 猜数字大小 II
我们正在玩一个猜数游戏,游戏规则如下:

我从 1 到 n 之间选择一个数字。
你来猜我选了哪个数字。
如果你猜到正确的数字,就会 赢得游戏 。
如果你猜错了,那么我会告诉你,我选的数字比你的 更大或者更小 ,并且你需要继续猜数。
每当你猜了数字 x 并且猜错了的时候,你需要支付金额为 x 的现金。如果你花光了钱,就会 输掉游戏 。
给你一个特定的数字 n ,返回能够 确保你获胜 的最小现金数,不管我选择那个数字 。

688. 骑士在棋盘上的概率
思路:动态规划f[step][i][j]表示走了step步走到i,j的概率。f[step][i][j]都是由8个方向上的f[step][ni][nj]/8转移得到。一个技巧:将从row、column位置走k步改为从整个棋盘走k步走到row、column位置的概率。

887. 鸡蛋掉落
给你 k 枚相同的鸡蛋,并可以使用一栋从第 1 层到第 n 层共有 n 层楼的建筑。
已知存在楼层 f ,满足 0 <= f <= n ,任何从 高于 f 的楼层落下的鸡蛋都会碎,从 f 楼层或比它低的楼层落下的鸡蛋都不会破。
每次操作,你可以取一枚没有碎的鸡蛋并把它从任一楼层 x 扔下(满足 1 <= x <= n)。如果鸡蛋碎了,你就不能再次使用它。如果某枚鸡蛋扔下后没有摔碎,则可以在之后的操作中 重复使用 这枚鸡蛋。
请你计算并返回要确定 f 确切的值 的 最小操作次数 是多少?

思路:乍一看好像可以二分,但是这样的话也就没有用上k,另外二分的时候并没有考虑扔鸡蛋如果扔碎的代价,此题可以使用动态规划,dp[k][n]表示当前有k个鸡蛋,在n层楼扔鸡蛋的最小次数。
第 x 楼扔鸡蛋的时候:
如果鸡蛋不碎,那么状态变成 (k, n-x),即我们鸡蛋的数目不变,但答案只可能在上方的 n-x层楼了。也就是说,我们把原问题缩小成了一个规模为 (k, n-x)的子问题;
如果鸡蛋碎了,那么状态变成(k−1,x−1),即我们少了一个鸡蛋,但我们知道答案只可能在第 x楼下方的 x-1层楼中了。也就是说,我们把原问题缩小成了一个规模为 (k-1, x-1)的子问题。
dp(k,n)=1+ 1≤x≤nmin (max(dp(k−1,x−1),dp(k,n−x)))。
这样复杂度整体为O(knn),因此需要优化一下计算当前dp[k][n]的逻辑,原本我们是枚举仍的楼层,然后首先dp在k固定的情况下,肯定是个单调递增的,这个可以理解,楼层越高,操作次数会增加。而dp(k−1,x−1)和dp(k,n−x)(忽略第一维的k)一个递增,一个递减(在x增加的时候),这时候就跟下图差不多在这里插入图片描述
要在这两者取大的最小值,则肯定要取到t1和t2的交点位置。而这交点的两侧,符合二分性(如图),因此可以二分,另外注意,两者的函数都不是连续的而是离散的,比如只能取整数1,2,3。因此该交点可能不是整数,这时候只有取到离该交点X最近的x0和x1,形成x0<X<x1,再加上可以取到的情况,则为x0<=X<=x1,而只要得到这两个点,就可以计算当前dp值了(不言而喻)。

72. 编辑距离
给你两个单词 word1 和 word2, 请返回将 word1 转换成 word2 所使用的最少操作数 。
你可以对一个单词进行如下三种操作:
插入一个字符
删除一个字符
替换一个字符

分情况讨论,首先插入和删除有对称性,因此只考虑插入和替换的情况。
因此有以下三种情况:
A插入、B插入、A or B修改。
设dp[i][j]表示A0,A1,…,Ai和B0,B1,…,Bj的编辑距离。根据上述情况,考虑如何转换得到dp[i][j]。

926. 将字符串翻转到单调递增
如果一个二进制字符串,是以一些 0(可能没有 0)后面跟着一些 1(也可能没有 1)的形式组成的,那么该字符串是 单调递增 的。
给你一个二进制字符串 s,你可以将任何 0 翻转为 1 或者将 1 翻转为 0 。
返回使 s 单调递增的最小翻转次数。

871. 最低加油次数
定义dp[j]表示加油j次可以行驶的最大距离,在更新完dp数组后,从下标的小到大遍历如果dp[i]大于target则可以直接返回。
如何更新dp数组?dp[0]=startfuel很明显,然后按照距离遍历每个加油站,每次根据dp[i]是否大于该加油站距离更新dpi

522. 最长特殊序列 II
本质上是在考LCS,本题需要先知道,如果其中一个str是其他str的子str,那么根本就出不来special str。而如果一个str都不是其他str的子str,那么该str的special str就是自己本身。指知道这一点,直接二重循环就好了。

873. 最长的斐波那契子序列的长度
fibonacci两个数确定总序列,f[i][j]:arri为倒数第一个数、arrj为倒数第二个数构成的序列长度,倒数第三个数可以得到、记录一下arr[i]到i的map,然后可以得到倒数第三个数的index,那么可以得到转移方程式

猜你喜欢

转载自blog.csdn.net/weixin_45719581/article/details/119740821
今日推荐