mirror of
https://github.com/youngyangyang04/leetcode-master.git
synced 2025-07-09 02:53:31 +08:00
Merge branch 'master' of github.com:jinbudaily/leetcode-master
This commit is contained in:
@ -396,7 +396,7 @@
|
||||
|
||||
* [图论:深度优先搜索理论基础](./problems/图论深搜理论基础.md)
|
||||
* [图论:797.所有可能的路径](./problems/0797.所有可能的路径.md)
|
||||
* [图论:广度优先搜索理论基础](./problems/图论广索理论基础.md)
|
||||
* [图论:广度优先搜索理论基础](./problems/图论广搜理论基础.md)
|
||||
* [图论:200.岛屿数量.深搜版](./problems/0200.岛屿数量.深搜版.md)
|
||||
* [图论:200.岛屿数量.广搜版](./problems/0200.岛屿数量.广搜版.md)
|
||||
* [图论:695.岛屿的最大面积](./problems/0695.岛屿的最大面积.md)
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
输入:words = ["bella","label","roller"]
|
||||
输出:["e","l","l"]
|
||||
|
||||
示例 2:
|
||||
|
||||
输入:words = ["cool","lock","cook"]
|
||||
|
@ -16,13 +16,13 @@
|
||||
|
||||
## dfs 与 bfs 区别
|
||||
|
||||
提到深度优先搜索(dfs),就不得不说和广度优先有什么区别(bfs)
|
||||
提到深度优先搜索(dfs),就不得不说和广度优先搜索(bfs)有什么区别
|
||||
|
||||
先来了解dfs的过程,很多录友可能对dfs(深度优先搜索),bfs(广度优先搜索)分不清。
|
||||
|
||||
先给大家说一下两者大概的区别:
|
||||
|
||||
* dfs是可一个方向去搜,不到黄河不回头,直到遇到绝境了,搜不下去了,在换方向(换方向的过程就涉及到了回溯)。
|
||||
* dfs是可一个方向去搜,不到黄河不回头,直到遇到绝境了,搜不下去了,再换方向(换方向的过程就涉及到了回溯)。
|
||||
* bfs是先把本节点所连接的所有节点遍历一遍,走到下一个节点的时候,再把连接节点的所有节点遍历一遍,搜索方向更像是广度,四面八方的搜索过程。
|
||||
|
||||
当然以上讲的是,大体可以这么理解,接下来 我们详细讲解dfs,(bfs在用单独一篇文章详细讲解)
|
||||
@ -60,20 +60,20 @@
|
||||
|
||||
上图演示中,其实我并没有把 所有的 从节点1 到节点6的dfs(深度优先搜索)的过程都画出来,那样太冗余了,但 已经把dfs 关键的地方都涉及到了,关键就两点:
|
||||
|
||||
* 搜索方向,是认准一个方向搜,直到碰壁之后在换方向
|
||||
* 搜索方向,是认准一个方向搜,直到碰壁之后再换方向
|
||||
* 换方向是撤销原路径,改为节点链接的下一个路径,回溯的过程。
|
||||
|
||||
## 代码框架
|
||||
|
||||
正式因为dfs搜索可一个方向,并需要回溯,所以用递归的方式来实现是最方便的。
|
||||
正是因为dfs搜索可一个方向,并需要回溯,所以用递归的方式来实现是最方便的。
|
||||
|
||||
很多录友对回溯很陌生,建议先看看码随想录,[回溯算法章节](https://programmercarl.com/回溯算法理论基础.html)。
|
||||
很多录友对回溯很陌生,建议先看看代码随想录,[回溯算法章节](https://programmercarl.com/回溯算法理论基础.html)。
|
||||
|
||||
有递归的地方就有回溯,那么回溯在哪里呢?
|
||||
|
||||
就地递归函数的下面,例如如下代码:
|
||||
|
||||
```
|
||||
```cpp
|
||||
void dfs(参数) {
|
||||
处理节点
|
||||
dfs(图,选择的节点); // 递归
|
||||
@ -89,7 +89,7 @@ void dfs(参数) {
|
||||
|
||||
我们在回顾一下[回溯法](https://programmercarl.com/回溯算法理论基础.html)的代码框架:
|
||||
|
||||
```
|
||||
```cpp
|
||||
void backtracking(参数) {
|
||||
if (终止条件) {
|
||||
存放结果;
|
||||
@ -106,7 +106,7 @@ void backtracking(参数) {
|
||||
|
||||
回溯算法,其实就是dfs的过程,这里给出dfs的代码框架:
|
||||
|
||||
```
|
||||
```cpp
|
||||
void dfs(参数) {
|
||||
if (终止条件) {
|
||||
存放结果;
|
||||
@ -136,7 +136,7 @@ void dfs(参数) {
|
||||
|
||||
1. 确认递归函数,参数
|
||||
|
||||
```
|
||||
```cpp
|
||||
void dfs(参数)
|
||||
```
|
||||
|
||||
@ -146,7 +146,7 @@ void dfs(参数)
|
||||
|
||||
例如这样:
|
||||
|
||||
```
|
||||
```cpp
|
||||
vector<vector<int>> result; // 保存符合条件的所有路径
|
||||
vector<int> path; // 起点到终点的路径
|
||||
void dfs (图,目前搜索的节点)
|
||||
@ -158,7 +158,7 @@ void dfs (图,目前搜索的节点)
|
||||
|
||||
终止条件很重要,很多同学写dfs的时候,之所以容易死循环,栈溢出等等这些问题,都是因为终止条件没有想清楚。
|
||||
|
||||
```
|
||||
```cpp
|
||||
if (终止条件) {
|
||||
存放结果;
|
||||
return;
|
||||
@ -173,7 +173,7 @@ if (终止条件) {
|
||||
|
||||
一般这里就是一个for循环的操作,去遍历 目前搜索节点 所能到的所有节点。
|
||||
|
||||
```
|
||||
```cpp
|
||||
for (选择:本节点所连接的其他节点) {
|
||||
处理节点;
|
||||
dfs(图,选择的节点); // 递归
|
||||
|
@ -338,6 +338,64 @@ public class BagProblem {
|
||||
|
||||
```
|
||||
|
||||
```java
|
||||
import java.util.Arrays;
|
||||
|
||||
public class BagProblem {
|
||||
public static void main(String[] args) {
|
||||
int[] weight = {1,3,4};
|
||||
int[] value = {15,20,30};
|
||||
int bagSize = 4;
|
||||
testWeightBagProblem(weight,value,bagSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化 dp 数组做了简化(给物品增加冗余维)。这样初始化dp数组,默认全为0即可。
|
||||
* dp[i][j] 表示从下标为[0 - i-1]的物品里任意取,放进容量为j的背包,价值总和最大是多少。
|
||||
* 其实是模仿背包重量从 0 开始,背包容量 j 为 0 的话,即dp[i][0],无论是选取哪些物品,背包价值总和一定为 0。
|
||||
* 可选物品也可以从无开始,也就是没有物品可选,即dp[0][j],这样无论背包容量为多少,背包价值总和一定为 0。
|
||||
* @param weight 物品的重量
|
||||
* @param value 物品的价值
|
||||
* @param bagSize 背包的容量
|
||||
*/
|
||||
public static void testWeightBagProblem(int[] weight, int[] value, int bagSize){
|
||||
|
||||
// 创建dp数组
|
||||
int goods = weight.length; // 获取物品的数量
|
||||
int[][] dp = new int[goods + 1][bagSize + 1]; // 给物品增加冗余维,i = 0 表示没有物品可选
|
||||
|
||||
// 初始化dp数组,默认全为0即可
|
||||
// 填充dp数组
|
||||
for (int i = 1; i <= goods; i++) {
|
||||
for (int j = 1; j <= bagSize; j++) {
|
||||
if (j < weight[i - 1]) { // i - 1 对应物品 i
|
||||
/**
|
||||
* 当前背包的容量都没有当前物品i大的时候,是不放物品i的
|
||||
* 那么前i-1个物品能放下的最大价值就是当前情况的最大价值
|
||||
*/
|
||||
dp[i][j] = dp[i - 1][j];
|
||||
} else {
|
||||
/**
|
||||
* 当前背包的容量可以放下物品i
|
||||
* 那么此时分两种情况:
|
||||
* 1、不放物品i
|
||||
* 2、放物品i
|
||||
* 比较这两种情况下,哪种背包中物品的最大价值最大
|
||||
*/
|
||||
dp[i][j] = Math.max(dp[i - 1][j] , dp[i - 1][j - weight[i - 1]] + value[i - 1]); // i - 1 对应物品 i
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 打印dp数组
|
||||
for(int[] arr : dp){
|
||||
System.out.println(Arrays.toString(arr));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### python
|
||||
无参数版
|
||||
```python
|
||||
|
Reference in New Issue
Block a user