LeetCode动态规划DP补充
leetcode专栏之外,有些没有刷到的DP的题,在这里补充了
Rookie2Master
CSDN is like shit and is no longer used
展开
-
LeetCode回文问题总结,回文子串,回文子序列等
1. LeetCode 5. 最长回文子串(求长度)传送门题目: 给定一个字符串 s,找到 s 中最长的回文子串。你可以假设s 的最大长度为 1000。输入: “babad”输出: “bab” 注意: “aba” 也是一个有效答案。假设字符串s的长度为length,建立一个length*length的矩阵dp。令 dp[i][j] 表示 S[i] 至 S[j] 所表示的子串是否是回文子串。当 i == j,dp[i][j] 是回文子串(单字符都是回文子串);当 j -原创 2020-11-05 09:41:01 · 833 阅读 · 0 评论 -
leetcode119. 杨辉三角 II
传送门题目:给定一个非负索引 k,其中 k ≤ 33,返回杨辉三角的第 k 行输入: 3输出: [1,3,3,1]列优化的动态规划,注意列优化后的列遍历方向 public List<Integer> getRow(int k) { List<Integer> ans = new ArrayList<>(); int[] dp = new int[k + 1]; for (int i = 0; i <= k原创 2020-09-07 17:14:36 · 114 阅读 · 0 评论 -
背包问题(图解优化过程)
图片太大,上传不了。。。见dp的word版最后的总结,那里粘的有图片。原创 2020-09-06 18:25:21 · 448 阅读 · 0 评论 -
leetcode698. 划分为k个相等的子集
传送门题目:给定一个整数数组 nums 和一个正整数 k,找出是否有可能把这个数组分成 k 个非空子集,其总和都相等。输入: nums = [4, 3, 2, 3, 5, 2, 1], k = 4 输出: True说明: 有可能将其分成 4 个子集(5),(1,4),(2,3),(2,3)等于总和。这种找子集的题,先求和,然后除以子集个数,得到每一部分的子集和,然后凑子集和 int[] bucket; // 放k的子集的和 public boolean canP原创 2020-09-03 17:37:12 · 717 阅读 · 0 评论 -
leetcode740. 删除与获得点数
传送门题目:给定一个整数数组 nums ,你可以对它进行一些操作。每次操作中,选择任意一个 nums[i] ,删除它并获得 nums[i] 的点数。之后,你必须删除每个等于 nums[i] - 1 或 nums[i] + 1 的元素。开始你拥有 0 个点数。返回你能通过这些操作获得的最大点数。输入: nums = [2, 2, 3, 3, 3, 4] 输出: 9解释:删除 3 来获得 3 个点数,接着要删除两个 2 和 4 。之后,再次原创 2020-09-03 17:35:04 · 187 阅读 · 0 评论 -
leetcode688. “马”在棋盘上的概率
传送门题目:已知一个 NxN 的国际象棋棋盘,棋盘的行号和列号都是从 0 开始。即最左上角的格子记为 (0, 0),最右下角的记为 (N-1, N-1)。 现有一个 “马”(也译作 “骑士”)位于 (r, c) ,并打算进行 K 次移动。如下图所示,国际象棋的 “马” 每一步先沿水平或垂直方向移动 2 个格子,然后向与之相垂直的方向再移动 1 个格子,共有 8 个可选的位置。现在 “马” 每一步都从可选的位置(包括棋盘外部的)中独立随机地选择一个进行移动,直到移动了 K 次或跳到了棋盘外面。 求移原创 2020-09-03 17:32:38 · 191 阅读 · 0 评论 -
leetcode650. 只有两个键的键盘(复制粘贴次数)
传送门题目:最初在一个记事本上只有一个字符 ‘A’。你每次可以对这个记事本进行两种操作:Copy All (复制全部) : 你可以复制这个记事本中的所有字符(部分的复制是不允许的)。Paste (粘贴) : 你可以粘贴你上一次复制的字符。给定一个数字 n 。你需要使用最少的操作次数,在记事本中打印出恰好 n 个 ‘A’。输出能够打印出 n 个 ‘A’ 的最少操作次数。输入: 3输出: 3最初, 我们只有一个字符 ‘A’。第 1 步, 我们使用 Copy All 操作。第 2 步, 我们使用原创 2020-09-03 17:29:47 · 600 阅读 · 0 评论 -
leetcode646. 最长数对链
传送门题目:给出 n 个数对。 在每一个数对中,第一个数字总是比第二个数字小。现在,我们定义一种跟随关系,当且仅当 b < c 时,数对(c, d) 才可以跟在 (a, b) 后面。我们用这种形式来构造一个数对链。给定一个对数集合,找出能够形成的最长数对链的长度。你不需要用到所有的数对,你可以以任何顺序选择其中的一些数对来构造。输入: [[1,2], [2,3], [3,4]]输出: 2 解释: 最长的数对链是 [1,2] -> [3,4]方法1原创 2020-09-03 17:08:09 · 146 阅读 · 0 评论 -
leetcode576. 出界的路径数
传送门题目:给定一个 m × n 的网格和一个球。球的起始坐标为 (i,j) ,你可以将球移到相邻的单元格内,或者往上、下、左、右四个方向上移动使球穿过网格边界。但是,你最多可以移动 N 次。找出可以将球移出边界的路径数量。答案可能非常大,返回 结果 mod pow(10,9) + 7 的值。输入: m = 2, n = 2, N = 2, i = 0, j = 0输出: 6动态规划, dp[i][j][k]表示从(i, j)开始在k步内移除边界的路径数. 可知dp[i][j][k]只与(i,原创 2020-09-02 09:16:59 · 178 阅读 · 3 评论 -
leetcode523. 连续的子数组和
传送门题目:给定一个包含 非负数 的数组和一个目标 整数 k,编写一个函数来判断该数组是否含有连续的子数组,其大小至少为 2,且总和为 k 的倍数,即总和为 n*k,其中 n 也是一个整数。输入:[23,2,4,6,7], k = 6 输出:True解释:[2,4] 是一个大小为 2 的子数组,并且和为 6。暴力超时: public boolean checkSubarraySum(int[] nums, int k) { if (nums.l原创 2020-09-02 09:09:19 · 386 阅读 · 0 评论 -
leetcode467. 环绕字符串中唯一的子字符串
传送门题目:把字符串 s 看作是“abcdefghijklmnopqrstuvwxyz”的无限环绕字符串,所以 s 看起来是这样的:"…zabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd…". 现在我们有了另一个字符串 p 。你需要的是找出 s 中有多少个唯一的 p 的非空子串,尤其是当你的输入是字符串 p ,你需要输出字符串 s 中 p 的不同的非空子串的数目。注意: p 仅由小写的英文字母组成,p 的大小可能超过 10000。输入:原创 2020-09-02 09:03:34 · 314 阅读 · 0 评论 -
leetcode474. 一和零
传送门题目:假设你分别支配着 m 个 0 和 n 个 1。另外,还有一个仅包含 0 和 1 字符串的数组。你的任务是使用给定的 m 个 0 和 n 个 1 ,找到能拼出存在于数组中的字符串的最大数量。每个 0 和 1 至多被使用一次。输入: Array = {“10”, “0001”, “111001”, “1”, “0”}, m = 5, n = 3输出: 4解释: 总共 4 个字符串可以通过 5 个 0 和 3 个 1 拼出,即 “10”,“0001”,“1”,“0” 。先熟悉一下 0-1原创 2020-09-02 09:00:08 · 146 阅读 · 0 评论 -
leetcode718. 最长重复子数组
传送门题目:给两个整数数组 A 和 B ,返回两个数组中公共的、长度最长的子数组的长度。输入: A: [1,2,3,2,1] B: [3,2,1,4,7]输出: 3解释: 长度最长的公共子数组是 [3, 2, 1]没有列优化的dp,比1143简单了 public int findLength(int[] A, int[] B) { if (A.length == 0 || B.length == 0) return 0;原创 2020-09-02 08:57:20 · 131 阅读 · 0 评论 -
leetcode712. 两个字符串的最小ASCII删除和(最短非公共子序列)
传送门题目:给定两个字符串s1, s2,找到使两个字符串相等所需删除字符的ASCII值的最小和。输入: s1 = “sea”, s2 = “eat”输出: 231解释: 在 “sea” 中删除 “s” 并将 “s” 的值(115)加入总和。在 “eat” 中删除 “t” 并将 116 加入总和。结束时,两个字符串相等,115 + 116 = 231 就是符合条件的最小和和1143题求的是互补的序列动态过程中有三种状态(这里没有在字符串前加冗余字符,所以dp[i]比较的是字符s[i-1])1原创 2020-09-02 08:55:50 · 427 阅读 · 0 评论 -
leetcode1143. 最长公共子序列
传送门题目:给定两个字符串 text1 和 text2,返回这两个字符串的最长公共子序列的长度。一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。例如,“ace” 是 “abcde” 的子序列,但 “aec” 不是 “abcde” 的子序列。两个字符串的「公共子序列」是这两个字符串所共同拥有的子序列。 若这两个字符串没有公共子序列,则返回 0。输入:text1 = “abcde”, text2 = “ac原创 2020-09-02 08:51:44 · 130 阅读 · 0 评论 -
leetcode673. 最长递增子序列的个数
传送门题目:给定一个未排序的整数数组,找到最长递增子序列的个数。示例 1:输入: [1,3,5,4,7]输出: 2解释: 有两个最长递增子序列,分别是 [1, 3, 4, 7] 和[1, 3, 5, 7]。示例 2:输入: [2,2,2,2,2]输出: 5解释: 最长递增子序列的长度是1,并且存在5个子序列的长度为1,因此输出5。假设对于以 nums[i] 结尾的序列,我们知道最长序列的长度 length[i],以及具有该长度的序列的 count[i]。对于每一个 i<j 和一个原创 2020-09-02 08:48:15 · 143 阅读 · 0 评论 -
leetcode518. 零钱兑换 II
零钱兑换 II题目:给定不同面额的硬币和一个总金额。计算可以凑成总金额的硬币组合数。假设每一种面额的硬币有无限个。输入: amount = 5, coins = [1, 2, 5] 输出: 4解释: 有四种方式可以凑成总金额:5=55=2+2+15=2+1+1+15=1+1+1+1+1相对于377 组合总和IV只是把内外循环i和j互换了一下(377题是有顺序的,这题的组合是没有顺序的)虽然只是把循环位置互换了一下,dp方程也不变,但是思路是不一样的.原创 2020-09-02 08:43:48 · 175 阅读 · 0 评论 -
leetcode674. 最长连续递增序列
传送门题目:给定一个未经排序的整数数组,找到最长且连续的的递增序列,并返回该序列的长度。输入: [1,3,5,4,7] 输出: 3解释: 最长连续递增序列是 [1,3,5], 长度为3。尽管 [1,3,5,7] 也是升序的子序列, 但它不是连续的,因为5和7在原数组里被4隔开。也是子序列,但是没有用到什么算法,就是单纯数组题 public int findLengthOfLCIS(int[] nums) { if (nums.length <原创 2020-09-02 08:44:05 · 100 阅读 · 0 评论 -
leetcode516. 最长回文子序列
传送门题目:给定一个字符串 s ,找到其中最长的回文子序列,并返回该序列的长度。可以假设 s 的最大长度为 1000 。输入: "bbbab" 输出:4 一个可能的最长回文子序列为 "bbbb"。我们说这个问题对 dp 数组的定义是:在子串 s[i..j] 中,最长回文子序列的长度为 dp[i][j]。一定要记住这个定义才能理解算法。为啥这个问题要这样定义二维的 dp 数组呢?我们多次提到,找状态转移需要归纳思维,说白了就是如何从已原创 2020-09-01 20:33:18 · 344 阅读 · 0 评论 -
leetcode392. 判断子序列
传送门题目: 给定字符串 s 和 t ,判断 s 是否为 t 的子序列。s = “abc”, t = “ahbgdc” 返回 true.s = “axc”, t = “ahbgdc” 返回 false.双指针一起走 注意:时间是n 不是 n*m public boolean isSubsequence(String s, String t) { if (s.length() == 0) return true; if (t.length() == 0) r原创 2020-09-01 20:28:59 · 152 阅读 · 0 评论 -
leetcode486. 预测赢家
传送门题目:给定一个表示分数的非负整数数组。 玩家1从数组任意一端拿取一个分数,随后玩家2继续从剩余数组任意一端拿取分数,然后玩家1拿,……。每次一个玩家只能拿取一个分数,分数被拿取之后不再可取。直到没有剩余分数可取时游戏结束。最终获得分数总和最多的玩家获胜。给定一个表示分数的数组,预测玩家1是否会成为赢家。你可以假设每个玩家的玩法都会使他的分数最大化。输入: [1, 5, 2] 输出: False解释: 一开始,玩家1可以从1和2中进行选择。 如果他选择2(或者1)原创 2020-09-01 20:19:11 · 142 阅读 · 0 评论 -
leetcode464. 我能赢吗
传送门题目:在 “100 game” 这个游戏中,两名玩家轮流选择从 1 到 10 的任意整数,累计整数和,先使得累计整数和达到 100 的玩家,即为胜者。如果我们将游戏规则改为 “玩家不能重复使用整数” 呢?例如,两个玩家可以轮流从公共整数池中抽取从 1 到 15 的整数(不放回),直到累计整数和 >= 100。给定一个整数 maxChoosableInteger (整数池中可选择的最大数)和另一个整数 desiredTotal(累计和),判断先出手的玩家是否能稳赢(假设两位玩家游戏时都表现原创 2020-09-01 20:15:48 · 192 阅读 · 0 评论 -
leetcode413. 等差数列划分
传送门题目:如果一个数列至少有三个元素,并且任意两个相邻元素之差相同,则称该数列为等差数列。例如,以下数列为等差数列:1, 3, 5, 7, 97, 7, 7, 73, -1, -5, -9以下数列不是等差数列。1, 1, 2, 5, 7函数要返回数组 A 中所有为等差数组的子数组个数。A = [1, 2, 3, 4] 返回: 3, A 中有三个子等差数组: [1, 2, 3], [2, 3, 4] 以及自身 [1, 2, 3, 4]。方法1.滑动窗口滑动窗口用len动态表示窗口l原创 2020-09-01 20:12:10 · 238 阅读 · 0 评论 -
leetcode322. leetcode518零钱兑换
传送门题目:给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。输入: coins = [1, 2, 5], amount = 11 输出: 3 解释: 11 = 5 + 5 + 1 输入: coins = [2], amount = 3 输出: -1最大最小问题,见attention public int coinChange(int[] coins,原创 2020-09-01 19:55:00 · 231 阅读 · 0 评论 -
leetcode377. 组合总和 Ⅳ
传送门题目:给定一个由正整数组成且不存在重复数字的数组,找出和为给定目标正整数的组合的个数。nums = [1, 2, 3] target = 4所有可能的组合为:(1, 1, 1, 1)(1, 1, 2)(1, 2, 1)(1, 3)(2, 1, 1)(2, 2)(3, 1) 顺序不同的序列被视作不同的组合。 因此输出为 7。见博客DP总结,典型的第2类问题。比如[1,2,3]在计算构成8的排列有几个时即dp[原创 2020-09-01 19:52:51 · 411 阅读 · 0 评论 -
leetcode376. 摆动序列
传送门题目:如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为摆动序列。第一个差(如果存在的话)可能是正数或负数。少于两个元素的序列也是摆动序列。通过从原始序列中删除一些(也可以不删除)元素来获得子序列,剩下的元素保持其原始顺序。输入: [1,17,5,10,13,15,10,5,16,8] 输出: 7 解释: 这个序列包含几个长度为 7 摆动序列,其中一个可为[1,17,10,13,10,16,8]。方法1. 动态规划 public int wiggle原创 2020-09-01 19:39:47 · 256 阅读 · 0 评论 -
动态规划总结:子序列,子数组(子串)
子序列和子数组:dp[i][j]更新: case1:判断两个字符是否相等: 如果输入只有一个串,这两个字符就是一个串里取得,比如最长回文子串516。 如果输入两个串,这两个字符就是两个字符串取得,比如1143最长公共子序列。 方程一般是 if (s1.charAt(i) == s2.charAt(j)) dp[i][j] = dp[i - 1][j - 1] + x; 输入只有一个串的时候,s1就是s2; x可以是0,1,2这种,比如问的原创 2020-09-01 10:14:16 · 848 阅读 · 0 评论 -
leetcode374&375. 猜数字大小总结
leetcode374. 猜数字大小(二分的坑)题目:猜数字游戏的规则如下:每轮游戏,系统都会从 1 到 n 随机选择一个数字。 请你猜选出的是哪个数字。如果你猜错了,系统会告诉你,你猜测的数字比系统选出的数字是大了还是小了。你可以通过调用一个预先定义好的接口 guess(int num) 来获取猜测结果,返回值一共有 3 种可能的情况(-1,1 或 0):-1 : 你猜测的数字比系统选出的数字大1 : 你猜测的数字比系统选出的数字小0 : 恭喜!你猜对了!输入: n = 10, pick原创 2020-08-30 12:06:24 · 511 阅读 · 0 评论 -
leetcode368. 最大整除子集
传送门题目:给出一个由无重复的正整数组成的集合,找出其中最大的整除子集,子集中任意一对 (Si,Sj) 都要满足:Si % Sj = 0 或 Sj % Si = 0。输入: [1,2,3]输出: [1,2] (当然, [1,3] 也正确) 如果有多个目标子集,返回其中任何一个均可。假如已经有一个满足上面条件的序列2 4 8, 若此时来一个8的倍数x,那么x一定是8 4 2的倍数,2 4 8 x依然满足条件。到了此处就发现可以大问题转换成子问题,于是联想到动态规划。并且在扩展序列的时候是原创 2020-08-30 11:59:26 · 126 阅读 · 0 评论 -
leetcode357. 计算各个位数不同的数字个数
传送门题目:给定一个非负整数 n,计算各位数字都不同的数字 x 的个数,其中 0 ≤ x < pow(10, n)。输入: 2 输出: 91解释: 答案应为除去 11,22,33,44,55,66,77,88,99 外,在 [0,100) 区间内的所有数字。 * 排列组合:n位有效数字 = 每一位都从 0~9 中选择,且不能以 0 开头 * 1位数字:0~9 10 * 2位数字:且第一位不能是0 9 * 9原创 2020-08-30 11:56:25 · 151 阅读 · 0 评论 -
leetcode343. 整数拆分
传送门题目:给定一个正整数 n (n>=2),将其拆分为至少两个正整数的和,并使这些整数的乘积最大化输入: 10 输出: 36解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36。方法1. 动态规划 public int integerBreak(int n) { int[] dp = new int[n + 1]; dp[1] = dp[2] = 1; for (int i = 3; i <原创 2020-08-28 20:13:05 · 97 阅读 · 0 评论 -
leetcode304. 二维区域和检索 - 矩阵不可变
传送门题目: 给定一个二维矩阵,计算其子矩形范围内元素的总和,该子矩阵的左上角为 (row1, col1) ,右下角为 (row2, col2)。上图子矩阵左上角 (row1, col1) = (2, 1) ,右下角(row2, col2) = (4, 3),该子矩形内元素的总和为 8。sumRegion(2, 1, 4, 3) -> 8 sumRegion(1, 1, 2, 2) -> 11 sumRegion(1, 2, 2, 4) ->原创 2020-08-28 20:10:17 · 149 阅读 · 0 评论 -
leetcode303. 区域和检索 - 数组不可变
传送门题目:给定一个整数数组 nums,求出数组从索引 i 到 j (i ≤ j) 范围内元素的总和,包含 i, j 两点。示例:给定 nums = [-2, 0, 3, -5, 2, -1],求和函数为 sumRange()sumRange(0, 2) -> 1sumRange(2, 5) -> -1sumRange(0, 5) -> -3注意: 会多次调用 sumRange 方法。记录前n项和,用sum(j) - sum(i) 得到 i到j的和原始方法:要原创 2020-08-28 20:00:37 · 205 阅读 · 0 评论 -
leetcode263&264 丑数总结
leetcode263 丑数题目: 编写一个程序判断给定的数是否为丑数。丑数就是只包含质因数 2, 3, 5 的正整数。示例 1:输入: 6输出: true解释: 6 = 2 × 31 也是丑数 public boolean isUgly(int num) { if (num == 0) return false; if (num == 1) return true; if (num % 2 == 0) return isUgly(num / 2原创 2020-08-28 19:58:44 · 124 阅读 · 0 评论 -
leetcode95. 不同的二叉搜索树 II
传送门题目:给定一个整数 n,生成所有由 1 … n 为节点所组成的 二叉搜索树 。输入:3输出:[ [1,null,3,2], [3,2,null,1], [3,1,null,null,2], [2,1,3], [1,null,2,null,3]]解释:以上的输出对应以下 5 种不同结构的二叉搜索树: 1 3 3 2 1 \ / / / \ \ 3 2原创 2020-08-28 17:41:00 · 92 阅读 · 1 评论 -
leetcode53. 最大子序和
传送门题目:输入一个整型数组。数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。输入: nums = [-2,1,-3,4,-1,2,1,-5,4]输出: 6解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。 public int maxSubArray(int[] nums) { int dp = nums[0]; int ans = dp; for (int i = 1; i < nums.length; ++i原创 2020-08-28 17:34:46 · 86 阅读 · 0 评论