文章目录

  • 系列文章目录
  • 前言
  • 题录
    • 509. 斐波那契数
    • 70. 爬楼梯
    • 746. 使用最小花费爬楼梯
    • 62. 不同路径
    • 63. 不同路径 II
    • 53. 最大子数组和
    • 343. 整数拆分
    • 96.不同的二叉搜索树

系列文章目录

一、 数组类型解题方法一:二分法
二、数组类型解题方法二:双指针法
三、数组类型解题方法三:滑动窗口
四、数组类型解题方法四:模拟
五、链表篇之链表的基础操作和经典题目
六、哈希表篇之经典题目
七、字符串篇之经典题目
八、字符串篇之 KMP
九、解题方法:双指针
十、栈与队列篇之经典题目
十 一、栈与队列篇之 top-K 问题
十 二、二叉树篇之二叉树的前中后序遍历
十 三、二叉树篇之二叉树的层序遍历及相关题目
十 四、二叉树篇之二叉树的属性相关题目
十 五、 二叉树篇之二叉树的修改与构造
十 六、 二叉树篇之二叉搜索树的属性
十 七、二叉树篇之公共祖先问题
十 八、二叉树篇之二叉搜索树的修改与构造
十 九、回溯算法篇之组合问题
二 十、回溯算法篇之分割、子集、全排列问题
二十一、贪心算法篇之入门题目
二十二、贪心算法篇之进阶题目
更新中 …


前言

刷题路线来自 :代码随想录
动态规划中每一个状态一定是由上一个状态推导出来的,例如青蛙跳台阶,第 N个台阶是从N -1 或者 N-2台阶上跳上来的。
解题步骤:

  1. 状态(dp数组以及下标的含义)
  2. 递推公式 和 循环结构
  3. 初始化
  4. 返回值

题录

509. 斐波那契数

Leetcode 链接

题解:
方式一:递归

class Solution {public int fib(int n) {if (n == 0 || n == 1) return n;return fib(n - 1) + fib(n - 2);}
}

方式二:动态规划

class Solution {public int fib(int n) {if (n == 0) return 0;if (n == 1) return 1;int[] dp = new int[n + 1];dp[0] = 0;dp[1] = 1;for (int i = 2; i <= n; i++) {dp[i] = dp[i - 1] + dp[i - 2];}return dp[n];}
}

空间优化:

class Solution {public int fib(int n) {if (n == 0) return 0;if (n == 1) return 1;int a = 0;int b = 1;int res = 0;for (int i = 2; i <= n; i++) {res = a + b;a = b;b = res;}return res;}
}

70. 爬楼梯

Leetcode 链接

题解:
第 N 层楼梯是由第 N - 1 或 N - 2 层跳上来的
dp 数组

class Solution {public int climbStairs(int n) {if (n == 1) return 1;int[] dp = new int[n + 1];dp[0] = 1;dp[1] = 1;for (int i = 2; i <= n; i++) {dp[i] = dp[i - 1] + dp[i - 2];}return dp[n];}
}

746. 使用最小花费爬楼梯

Leetcode 链接
给你一个整数数组 cost ,其中 cost[i] 是从楼梯第 i 个台阶向上爬需要支付的费用。一旦你支付此费用,即可选择向上爬一个或者两个台阶。
你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。请你计算并返回达到楼梯顶部的最低花费。

题解:

class Solution {public int minCostClimbingStairs(int[] cost) {int len = cost.length;int[] dp = new int[len];dp[0] = cost[0];dp[1] = cost[1];for (int i = 2; i < len; i++) {dp[i] = Math.min(dp[i - 1], dp[i - 2]) +cost[i];}return Math.min(dp[len - 1], dp[len - 2]);}
}

62. 不同路径

Leetcode 链接
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。问总共有多少条不同的路径?

题解:
状态(i, j):从(0,0) 到(i, j)的路径个数
状态方程:F(i,j) = F(i-1,j) + F(i,j-1)
初始状态: F(0,0) = F(0,j) = F(i,0) = 1

class Solution {public int uniquePaths(int m, int n) {int[][] dp = new int[m][n];for (int i = 0; i < m; i++) dp[i][0] = 1;for (int i = 0; i < n; i++) dp[0][i] = 1;for (int i = 1; i < m; i++) {for (int j = 1; j < n; j++) {dp[i][j] = dp[i - 1][j] + dp[i][j - 1];}}return dp[m - 1][n- 1];}
}

优化:
状态(i,j):从(0,0) 到(i,j)的路径个数
状态方程:F(i,j) = F(i-1,j) + F(i,j-1)
初始状态:F(0,j) = F(i,0) = 0, F(0,1) = 1或者F(1,0) = 1
返回结果:F(row,col)

class Solution {public int uniquePaths(int m, int n) {int[][] dp = new int[m + 1][n + 1];dp[0][1] = 1;for (int i = 1; i <= m; i++) {for (int j = 1; j <= n; j++) {dp[i][j] = dp[i - 1][j] + dp[i][j - 1];}}return dp[m][n];}
}

63. 不同路径 II

Leetcode 链接
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish”)。现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?网格中的障碍物和空位置分别用 1 和 0 来表示。


题解:
同上题,改变一下初始状态,第一排和第一列遇到石头将后边也初始化为 0,中间区域只让有石头的地方为 0

class Solution {public int uniquePathsWithObstacles(int[][] obstacleGrid) {int row = obstacleGrid.length;int col = obstacleGrid[0].length;int[][] dp = new int[row][col];for (int i = 0; i < row && obstacleGrid[i][0] == 0; i++) dp[i][0] = 1;for (int j = 0; j < col && obstacleGrid[0][j] == 0; j++) dp[0][j] = 1;for (int i = 1; i < row; i++) {for (int j = 1; j < col; j++) {if (obstacleGrid[i][j] == 0) {dp[i][j] = dp[i - 1][j] + dp[i][j -1];} else {dp[i][j] = 0;}}}return dp[row - 1][col - 1];}
}

优化:

class Solution {public int uniquePathsWithObstacles(int[][] obstacleGrid) {int row = obstacleGrid.length;int col = obstacleGrid[0].length;int[][] dp = new int[row + 1][col + 1];dp[0][1] = 1;for (int i = 1; i <= row; i++) {for (int j = 1; j <= col; j++) {if (obstacleGrid[i - 1][j - 1] == 1) {dp[i][j] = 0;}else {dp[i][j] = dp[i][j - 1] + dp[i -1][j];}}}return dp[row][col];}
}

53. 最大子数组和

Leetcode 链接
给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。子数组 是数组中的一个连续部分。

题解:
状态 dp[i]:算上 i 位置的最长连续子数组和
状态方程:dp[i] = Math.max(dp[i - 1] + nums[i], nums[i])
返回值:遍历过程中的 maxSum

class Solution {public int maxSubArray(int[] nums) {int[] dp = new int[nums.length];int maxSum = nums[0];dp[0] = nums[0];for (int i = 1; i < nums.length; i++) {dp[i] = Math.max(dp[i - 1] + nums[i], nums[i]);maxSum = Math.max(dp[i], maxSum);}return maxSum;}
}

343. 整数拆分

Leetcode 链接
给定一个正整数 n ,将其拆分为 k 个 正整数 的和( k >= 2 ),并使这些整数的乘积最大化。返回 你可以获得的最大乘积 。

题解:
例:5 可以分解为 1 + 4 、2 + 33 + 2、4 + 1
dp[1] * 4、dp[2] * 3dp[3] * 2 、dp[4] * 1、 但是这里并没有最大值
dp[2] = 1 * 1 = 1、dp[3] = 1 * 2 = 2最大的 dp[3] * 2 = 4
最大的是6: 5 = 2 + 3、2 * 3 = 6
而对于较大的数是更是满足递推公式的,所以递推公式中有:Math.max(dp[j] * (i - j), j * (i - j))
状态 dp[i]:整数 i 的拆分最大乘积
状态方程: Math.max(dp[i], Math.max(dp[j] * (i - j), j * (i - j)));
也可以这么理解,j * (i - j) 是单纯的把整数拆分为两个数相乘,而j * dp[i - j]是拆分成两个以及两个以上的个数相乘。
初始化:因为 k >= 2,dp[2] = 0
返回:dp[n]

class Solution {public int integerBreak(int n) {int[] dp = new int[n + 1];dp[2] = 1;for (int i = 3; i <= n; i++) {for (int j = 1; j <= i - 1; j++) {dp[i] = Math.max(dp[i], Math.max(dp[j] * (i - j), j * (i - j)));}}return dp[n];}
}

96.不同的二叉搜索树

Leetcode 链接

题解:
i 表示 为 n
j 表示以 j 为根节点
如:当 i = 3 时,j 分别为 1,2,3

class Solution {public int numTrees(int n) {int[] dp = new int[n + 1];dp[0] = 1;dp[1] = 1;for (int i = 2; i <= n; i++) {for (int j = 1; j <= i; j++) {dp[i] += dp[j- 1] * dp[i - j];}}return dp[n];}
}

Leetcode 刷题笔记(二十三) ——动态规划篇之基础题目相关推荐

  1. LeetCode刷题笔记- 15.三数之和

    LeetCode刷题笔记- 15.三数之和 C语言 题目 注意点 C语言 /*** Return an array of arrays of size *returnSize.* The sizes ...

  2. 小何同学的leetcode刷题笔记 基础篇(01)整数反转

    小何同学的leetcode刷题笔记 基础篇(01)整数反转[07] *** [01]数学取余法*** 对数字进行数位操作时,常见的方法便是用取余的方法提取出各位数字,再进行操作 操作(1):对10取余 ...

  3. 【leetcode刷题笔记】动态规划

    #[leetcode刷题笔记]动态规划 石子游戏 public boolean stoneGame(int[] piles) {int N = piles.length;// dp[i][j] is ...

  4. LeetCode刷题笔记-动态规划-day4

    文章目录 LeetCode刷题笔记-动态规划-day4 55. 跳跃游戏 1.题目 2.解题思路 3.代码 45. 跳跃游戏 II 1.题目 2.解题思路 3.代码 LeetCode刷题笔记-动态规划 ...

  5. LeetCode刷题笔记(算法思想 四)

    LeetCode刷题笔记(算法思想 四) 七.动态规划 斐波那契数列 70. 爬楼梯 198. 打家劫舍 213. 打家劫舍 II 信件错排 母牛生产 矩阵路径 64. 最小路径和 62. 不同路径 ...

  6. LeetCode刷题笔记2——数组2

    LeetCode刷题笔记2--数组2 重塑数组 题目 在 MATLAB 中,有一个非常有用的函数 reshape ,它可以将一个 m x n 矩阵重塑为另一个大小不同(r x c)的新矩阵,但保留其原 ...

  7. LeetCode刷题笔记汇总

    LeetCode刷题笔记汇总 第一次刷LeetCode写的一些笔记. 1.两数之和 3.无重复字符的最长子串 15.三数之和 18.四数之和 19.删除链表的倒数第 N 个结点 20.有效的括号 21 ...

  8. leetcode刷题笔记——二分查找

    leetcode刷题笔记--二分查找 目前完成的贪心相关的leetcode算法题序号: 中等:80,81 困难:4 来源:力扣(LeetCode) 链接:https://leetcode-cn.com ...

  9. 卷进大厂系列之LeetCode刷题笔记:二分查找(简单)

    LeetCode刷题笔记:二分查找(简单) 学算法,刷力扣,加油卷,进大厂! 题目描述 涉及算法 题目解答 学算法,刷力扣,加油卷,进大厂! 题目描述 力扣题目链接 给定一个 n 个元素有序的(升序) ...

  10. LeetCode刷题笔记第6题:Z字形变换

    LeetCode刷题笔记第6题:Z字形变换 想法: 要完成字符串根据给定的行数从上往下,从左到右完成Z字形排列.当只有一行时直接返回原字符串,当行数大于1时,先以行数构建一个行数数值个空字符串的列表, ...

最新文章

  1. 2W 字详解 Redis 6.0 集群环境搭建实践
  2. 2021年编程语言趋势预测:Python和JavaScript仍火热,Go不可小觑
  3. MYSQL——常用运算符和函数
  4. 你在京东购买的商品,是怎么出现在抖音里面的?
  5. Bootstrap+PHP fileinput 实现多图上传 这是ajax上传,只能单张单张图片地上传
  6. 转-Appium—驱动和常用功能的封装
  7. postman生成python代码_别再用手敲了,这个工具可以自动生成python爬虫代码
  8. 浅析Nginx 正向代理与反向代理
  9. Java日志框架之JUL(java util logging)详解
  10. 年轻人的第一台车“没了”,小米回应:新媒体同学抖错了机灵
  11. 小米10预计春节后见 售价超3500元没悬念
  12. aspnet_regsql.exe 工具参数解析
  13. 计算机技能大赛简讯内,【报道】2010学西城区职业高中计算机排版技能竞赛简讯...
  14. 在 360 度绩效评估中应该问的 20 个问题
  15. 怎样才能在微信朋友圈发长视频?
  16. 程序员面试之九阴真经
  17. pow函数以及math.h的一些坑
  18. android实现电话通信原理,电话通信原理.pdf
  19. convert函数用法小结
  20. OSChina 周二乱弹 —— 怎么制作妹子面

热门文章

  1. mysql基础7-MYSQL连接查询
  2. 一文弄懂nginx反向代理和负载均衡
  3. 一文掌握 Docker 技术体系
  4. 培养一个数据人才需要多少年?
  5. 为什么经常说Node.js不适合大型应用
  6. 卷积网络虽动人,胶囊网络更传“神”
  7. Android中native进程内存泄露的调试技巧
  8. 免费讲座:从草根到巨人——互联网时代的LAMP开源架构
  9. Tensorflow:模型调参
  10. python小技巧 - 如何成为Python高手