This commit is contained in:
youngyangyang04
2022-01-17 12:36:22 +08:00
parent ab26823862
commit 35bbec3e29
4 changed files with 75 additions and 78 deletions

View File

@ -4,7 +4,7 @@
</a> </a>
<p align="center"><strong><a href="https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A">参与本项目</a>,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!</strong></p> <p align="center"><strong><a href="https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A">参与本项目</a>,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!</strong></p>
## 63. 不同路径 II # 63. 不同路径 II
[力扣题目链接](https://leetcode-cn.com/problems/unique-paths-ii/) [力扣题目链接](https://leetcode-cn.com/problems/unique-paths-ii/)
@ -22,23 +22,22 @@
![](https://img-blog.csdnimg.cn/20210111204939971.png) ![](https://img-blog.csdnimg.cn/20210111204939971.png)
输入obstacleGrid = [[0,0,0],[0,1,0],[0,0,0]] * 输入obstacleGrid = [[0,0,0],[0,1,0],[0,0,0]]
输出2 * 输出2
解释: 解释:
3x3 网格的正中间有一个障碍物。 * 3x3 网格的正中间有一个障碍物。
从左上角到右下角一共有 2 条不同的路径: * 从左上角到右下角一共有 2 条不同的路径:
1. 向右 -> 向右 -> 向下 -> 向下 1. 向右 -> 向右 -> 向下 -> 向下
2. 向下 -> 向下 -> 向右 -> 向右 2. 向下 -> 向下 -> 向右 -> 向右
示例 2 示例 2
![](https://img-blog.csdnimg.cn/20210111205857918.png) ![](https://img-blog.csdnimg.cn/20210111205857918.png)
输入obstacleGrid = [[0,1],[0,0]] * 输入obstacleGrid = [[0,1],[0,0]]
输出1 * 输出1
提示: 提示:
* m == obstacleGrid.length * m == obstacleGrid.length
* n == obstacleGrid[i].length * n == obstacleGrid[i].length
* 1 <= m, n <= 100 * 1 <= m, n <= 100
@ -171,7 +170,7 @@ public:
## 其他语言版本 ## 其他语言版本
Java ### Java
```java ```java
class Solution { class Solution {
@ -199,7 +198,7 @@ class Solution {
``` ```
Python ### Python
```python ```python
class Solution: class Solution:
@ -262,7 +261,7 @@ class Solution:
``` ```
Go ### Go
```go ```go
func uniquePathsWithObstacles(obstacleGrid [][]int) int { func uniquePathsWithObstacles(obstacleGrid [][]int) int {
@ -308,8 +307,8 @@ func uniquePathsWithObstacles(obstacleGrid [][]int) int {
``` ```
Javascript ### Javascript
``` Javascript ```Javascript
var uniquePathsWithObstacles = function(obstacleGrid) { var uniquePathsWithObstacles = function(obstacleGrid) {
const m = obstacleGrid.length const m = obstacleGrid.length
const n = obstacleGrid[0].length const n = obstacleGrid[0].length

View File

@ -4,7 +4,7 @@
</a> </a>
<p align="center"><strong><a href="https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A">参与本项目</a>,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!</strong></p> <p align="center"><strong><a href="https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A">参与本项目</a>,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!</strong></p>
## 96.不同的二叉搜索树 # 96.不同的二叉搜索树
[力扣题目链接](https://leetcode-cn.com/problems/unique-binary-search-trees/) [力扣题目链接](https://leetcode-cn.com/problems/unique-binary-search-trees/)
@ -163,7 +163,7 @@ public:
## 其他语言版本 ## 其他语言版本
Java ### Java
```Java ```Java
class Solution { class Solution {
public int numTrees(int n) { public int numTrees(int n) {
@ -184,7 +184,7 @@ class Solution {
} }
``` ```
Python ### Python
```python ```python
class Solution: class Solution:
def numTrees(self, n: int) -> int: def numTrees(self, n: int) -> int:
@ -196,7 +196,7 @@ class Solution:
return dp[-1] return dp[-1]
``` ```
Go ### Go
```Go ```Go
func numTrees(n int)int{ func numTrees(n int)int{
dp:=make([]int,n+1) dp:=make([]int,n+1)
@ -210,7 +210,7 @@ func numTrees(n int)int{
} }
``` ```
Javascript ### Javascript
```Javascript ```Javascript
const numTrees =(n) => { const numTrees =(n) => {
let dp = new Array(n+1).fill(0); let dp = new Array(n+1).fill(0);

View File

@ -4,23 +4,22 @@
</a> </a>
<p align="center"><strong><a href="https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A">参与本项目</a>,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!</strong></p> <p align="center"><strong><a href="https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A">参与本项目</a>,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!</strong></p>
## 343. 整数拆分 # 343. 整数拆分
[力扣题目链接](https://leetcode-cn.com/problems/integer-break/) [力扣题目链接](https://leetcode-cn.com/problems/integer-break/)
给定一个正整数 n将其拆分为至少两个正整数的和并使这些整数的乘积最大化。 返回你可以获得的最大乘积。 给定一个正整数 n将其拆分为至少两个正整数的和并使这些整数的乘积最大化。 返回你可以获得的最大乘积。
示例 1: 示例 1:
输入: 2 * 输入: 2
输出: 1 * 输出: 1
* 解释: 2 = 1 + 1, 1 × 1 = 1。
\解释: 2 = 1 + 1, 1 × 1 = 1。
示例 2: 示例 2:
输入: 10 * 输入: 10
输出: 36 * 输出: 36
解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36。 * 解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36。
说明: 你可以假设 n 不小于 2 且不大于 58。 * 说明: 你可以假设 n 不小于 2 且不大于 58。
## 思路 ## 思路
@ -193,7 +192,7 @@ public:
## 其他语言版本 ## 其他语言版本
Java ### Java
```Java ```Java
class Solution { class Solution {
public int integerBreak(int n) { public int integerBreak(int n) {
@ -212,7 +211,7 @@ class Solution {
} }
``` ```
Python ### Python
```python ```python
class Solution: class Solution:
def integerBreak(self, n: int) -> int: def integerBreak(self, n: int) -> int:
@ -226,7 +225,8 @@ class Solution:
dp[i] = max(dp[i], max(j * (i - j), j * dp[i - j])) dp[i] = max(dp[i], max(j * (i - j), j * dp[i - j]))
return dp[n] return dp[n]
``` ```
Go
### Go
```golang ```golang
func integerBreak(n int) int { func integerBreak(n int) int {
/** /**
@ -256,7 +256,7 @@ func max(a,b int) int{
} }
``` ```
Javascript: ### Javascript
```Javascript ```Javascript
var integerBreak = function(n) { var integerBreak = function(n) {
let dp = new Array(n + 1).fill(0) let dp = new Array(n + 1).fill(0)

View File

@ -3,11 +3,12 @@
<img src="https://code-thinking-1253855093.file.myqcloud.com/pics/20210924105952.png" width="1000"/> <img src="https://code-thinking-1253855093.file.myqcloud.com/pics/20210924105952.png" width="1000"/>
</a> </a>
<p align="center"><strong><a href="https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A">参与本项目</a>,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!</strong></p> <p align="center"><strong><a href="https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A">参与本项目</a>,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!</strong></p>
# 动态规划关于01背包问题你该了解这些 # 动态规划关于01背包问题你该了解这些
这周我们正式开始讲解背包问题! 这周我们正式开始讲解背包问题!
背包问题的经典资料当然是:背包九讲。在公众号「代码随想录」后台回复:背包九讲,就可以获得背包九讲的PDF 背包问题的经典资料当然是:背包九讲。在公众号「代码随想录」后台回复:背包九讲,就可以获得背包九讲的pdf
但说实话,背包九讲对于小白来说确实不太友好,看起来还是有点费劲的,而且都是伪代码理解起来也吃力。 但说实话,背包九讲对于小白来说确实不太友好,看起来还是有点费劲的,而且都是伪代码理解起来也吃力。
@ -32,7 +33,7 @@ leetcode上没有纯01背包的问题都是01背包应用方面的题目
## 01 背包 ## 01 背包
N件物品和一个最多能背重量为W 的背包。第i件物品的重量是weight[i]得到的价值是value[i] 。**每件物品只能用一次**,求解将哪些物品装入背包里物品价值总和最大。 n件物品和一个最多能背重量为w 的背包。第i件物品的重量是weight[i]得到的价值是value[i] 。**每件物品只能用一次**,求解将哪些物品装入背包里物品价值总和最大。
![动态规划-背包问题](https://img-blog.csdnimg.cn/20210117175428387.jpg) ![动态规划-背包问题](https://img-blog.csdnimg.cn/20210117175428387.jpg)
@ -40,7 +41,7 @@ leetcode上没有纯01背包的问题都是01背包应用方面的题目
这样其实是没有从底向上去思考,而是习惯性想到了背包,那么暴力的解法应该是怎么样的呢? 这样其实是没有从底向上去思考,而是习惯性想到了背包,那么暴力的解法应该是怎么样的呢?
每一件物品其实只有两个状态,取或者不取,所以可以使用回溯法搜索出所有的情况,那么时间复杂度就是$O(2^n)$这里的n表示物品数量。 每一件物品其实只有两个状态,取或者不取,所以可以使用回溯法搜索出所有的情况,那么时间复杂度就是$o(2^n)$这里的n表示物品数量。
**所以暴力的解法是指数级别的时间复杂度。进而才需要动态规划的解法来进行优化!** **所以暴力的解法是指数级别的时间复杂度。进而才需要动态规划的解法来进行优化!**
@ -109,7 +110,7 @@ for (int j = 0 ; j < weight[0]; j++) { // 当然这一步如果把dp数组
dp[0][j] = 0; dp[0][j] = 0;
} }
// 正序遍历 // 正序遍历
for (int j = weight[0]; j <= bagWeight; j++) { for (int j = weight[0]; j <= bagweight; j++) {
dp[0][j] = value[0]; dp[0][j] = value[0];
} }
``` ```
@ -135,8 +136,8 @@ dp[0][j] 和 dp[i][0] 都已经初始化了,那么其他下标应该初始化
``` ```
// 初始化 dp // 初始化 dp
vector<vector<int>> dp(weight.size(), vector<int>(bagWeight + 1, 0)); vector<vector<int>> dp(weight.size(), vector<int>(bagweight + 1, 0));
for (int j = weight[0]; j <= bagWeight; j++) { for (int j = weight[0]; j <= bagweight; j++) {
dp[0][j] = value[0]; dp[0][j] = value[0];
} }
@ -160,7 +161,7 @@ for (int j = weight[0]; j <= bagWeight; j++) {
``` ```
// weight数组的大小 就是物品个数 // weight数组的大小 就是物品个数
for(int i = 1; i < weight.size(); i++) { // 遍历物品 for(int i = 1; i < weight.size(); i++) { // 遍历物品
for(int j = 0; j <= bagWeight; j++) { // 遍历背包容量 for(int j = 0; j <= bagweight; j++) { // 遍历背包容量
if (j < weight[i]) dp[i][j] = dp[i - 1][j]; if (j < weight[i]) dp[i][j] = dp[i - 1][j];
else dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]); else dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);
@ -174,7 +175,7 @@ for(int i = 1; i < weight.size(); i++) { // 遍历物品
``` ```
// weight数组的大小 就是物品个数 // weight数组的大小 就是物品个数
for(int j = 0; j <= bagWeight; j++) { // 遍历背包容量 for(int j = 0; j <= bagweight; j++) { // 遍历背包容量
for(int i = 1; i < weight.size(); i++) { // 遍历物品 for(int i = 1; i < weight.size(); i++) { // 遍历物品
if (j < weight[i]) dp[i][j] = dp[i - 1][j]; if (j < weight[i]) dp[i][j] = dp[i - 1][j];
else dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]); else dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);
@ -219,32 +220,32 @@ dp[i-1][j]和dp[i - 1][j - weight[i]] 都在dp[i][j]的左上角方向(包括
主要就是自己没有动手推导一下dp数组的演变过程如果推导明白了代码写出来就算有问题只要把dp数组打印出来对比一下和自己推导的有什么差异很快就可以发现问题了。 主要就是自己没有动手推导一下dp数组的演变过程如果推导明白了代码写出来就算有问题只要把dp数组打印出来对比一下和自己推导的有什么差异很快就可以发现问题了。
## 完整C++测试代码 ## 完整c++测试代码
```CPP ```cpp
void test_2_wei_bag_problem1() { void test_2_wei_bag_problem1() {
vector<int> weight = {1, 3, 4}; vector<int> weight = {1, 3, 4};
vector<int> value = {15, 20, 30}; vector<int> value = {15, 20, 30};
int bagWeight = 4; int bagweight = 4;
// 二维数组 // 二维数组
vector<vector<int>> dp(weight.size(), vector<int>(bagWeight + 1, 0)); vector<vector<int>> dp(weight.size(), vector<int>(bagweight + 1, 0));
// 初始化 // 初始化
for (int j = weight[0]; j <= bagWeight; j++) { for (int j = weight[0]; j <= bagweight; j++) {
dp[0][j] = value[0]; dp[0][j] = value[0];
} }
// weight数组的大小 就是物品个数 // weight数组的大小 就是物品个数
for(int i = 1; i < weight.size(); i++) { // 遍历物品 for(int i = 1; i < weight.size(); i++) { // 遍历物品
for(int j = 0; j <= bagWeight; j++) { // 遍历背包容量 for(int j = 0; j <= bagweight; j++) { // 遍历背包容量
if (j < weight[i]) dp[i][j] = dp[i - 1][j]; if (j < weight[i]) dp[i][j] = dp[i - 1][j];
else dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]); else dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);
} }
} }
cout << dp[weight.size() - 1][bagWeight] << endl; cout << dp[weight.size() - 1][bagweight] << endl;
} }
int main() { int main() {
@ -267,48 +268,45 @@ int main() {
## 其他语言版本 ## 其他语言版本
Java ### java
```java ```java
public static void main(String[] args) { public static void main(string[] args) {
int[] weight = {1, 3, 4}; int[] weight = {1, 3, 4};
int[] value = {15, 20, 30}; int[] value = {15, 20, 30};
int bagSize = 4; int bagsize = 4;
testWeightBagProblem(weight, value, bagSize); testweightbagproblem(weight, value, bagsize);
} }
public static void testWeightBagProblem(int[] weight, int[] value, int bagSize){ public static void testweightbagproblem(int[] weight, int[] value, int bagsize){
int wLen = weight.length, value0 = 0; int wlen = weight.length, value0 = 0;
//定义dp数组dp[i][j]表示背包容量为j时前i个物品能获得的最大价值 //定义dp数组dp[i][j]表示背包容量为j时前i个物品能获得的最大价值
int[][] dp = new int[wLen + 1][bagSize + 1]; int[][] dp = new int[wlen + 1][bagsize + 1];
//初始化背包容量为0时能获得的价值都为0 //初始化背包容量为0时能获得的价值都为0
for (int i = 0; i <= wLen; i++){ for (int i = 0; i <= wlen; i++){
dp[i][0] = value0; dp[i][0] = value0;
} }
//遍历顺序:先遍历物品,再遍历背包容量 //遍历顺序:先遍历物品,再遍历背包容量
for (int i = 1; i <= wLen; i++){ for (int i = 1; i <= wlen; i++){
for (int j = 1; j <= bagSize; j++){ for (int j = 1; j <= bagsize; j++){
if (j < weight[i - 1]){ if (j < weight[i - 1]){
dp[i][j] = dp[i - 1][j]; dp[i][j] = dp[i - 1][j];
}else{ }else{
dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - weight[i - 1]] + value[i - 1]); dp[i][j] = math.max(dp[i - 1][j], dp[i - 1][j - weight[i - 1]] + value[i - 1]);
} }
} }
} }
//打印dp数组 //打印dp数组
for (int i = 0; i <= wLen; i++){ for (int i = 0; i <= wlen; i++){
for (int j = 0; j <= bagSize; j++){ for (int j = 0; j <= bagsize; j++){
System.out.print(dp[i][j] + " "); system.out.print(dp[i][j] + " ");
} }
System.out.print("\n"); system.out.print("\n");
} }
} }
``` ```
### python
Python
```python ```python
def test_2_wei_bag_problem1(bag_size, weight, value) -> int: def test_2_wei_bag_problem1(bag_size, weight, value) -> int:
rows, cols = len(weight), bag_size + 1 rows, cols = len(weight), bag_size + 1
@ -343,26 +341,26 @@ if __name__ == "__main__":
``` ```
Go ### go
```go ```go
func test_2_wei_bag_problem1(weight, value []int, bagWeight int) int { func test_2_wei_bag_problem1(weight, value []int, bagweight int) int {
// 定义dp数组 // 定义dp数组
dp := make([][]int, len(weight)) dp := make([][]int, len(weight))
for i, _ := range dp { for i, _ := range dp {
dp[i] = make([]int, bagWeight+1) dp[i] = make([]int, bagweight+1)
} }
// 初始化 // 初始化
for j := bagWeight; j >= weight[0]; j-- { for j := bagweight; j >= weight[0]; j-- {
dp[0][j] = dp[0][j-weight[0]] + value[0] dp[0][j] = dp[0][j-weight[0]] + value[0]
} }
// 递推公式 // 递推公式
for i := 1; i < len(weight); i++ { for i := 1; i < len(weight); i++ {
//正序,也可以倒序 //正序,也可以倒序
for j := weight[i];j<= bagWeight ; j++ { for j := weight[i];j<= bagweight ; j++ {
dp[i][j] = max(dp[i-1][j], dp[i-1][j-weight[i]]+value[i]) dp[i][j] = max(dp[i-1][j], dp[i-1][j-weight[i]]+value[i])
} }
} }
return dp[len(weight)-1][bagWeight] return dp[len(weight)-1][bagweight]
} }
func max(a,b int) int { func max(a,b int) int {
@ -379,19 +377,19 @@ func main() {
} }
``` ```
javaScript: ### javascript
```js ```js
function testWeightBagProblem (wight, value, size) { function testweightbagproblem (wight, value, size) {
const len = wight.length, const len = wight.length,
dp = Array.from({length: len + 1}).map( dp = array.from({length: len + 1}).map(
() => Array(size + 1).fill(0) () => array(size + 1).fill(0)
); );
for(let i = 1; i <= len; i++) { for(let i = 1; i <= len; i++) {
for(let j = 0; j <= size; j++) { for(let j = 0; j <= size; j++) {
if(wight[i - 1] <= j) { if(wight[i - 1] <= j) {
dp[i][j] = Math.max( dp[i][j] = math.max(
dp[i - 1][j], dp[i - 1][j],
value[i - 1] + dp[i - 1][j - wight[i - 1]] value[i - 1] + dp[i - 1][j - wight[i - 1]]
) )