diff --git "a/problems/0070.\347\210\254\346\245\274\346\242\257\345\256\214\345\205\250\350\203\214\345\214\205\347\211\210\346\234\254.md" "b/problems/0070.\347\210\254\346\245\274\346\242\257\345\256\214\345\205\250\350\203\214\345\214\205\347\211\210\346\234\254.md" index 0da1ebeca5..26af256973 100644 --- "a/problems/0070.\347\210\254\346\245\274\346\242\257\345\256\214\345\205\250\350\203\214\345\214\205\347\211\210\346\234\254.md" +++ "b/problems/0070.\347\210\254\346\245\274\346\242\257\345\256\214\345\205\250\350\203\214\345\214\205\347\211\210\346\234\254.md" @@ -100,8 +100,8 @@ int main() { while (cin >> n >> m) { vector dp(n + 1, 0); dp[0] = 1; - for (int i = 1; i <= n; i++) { // 遍历物品 - for (int j = 1; j <= m; j++) { // 遍历背包 + for (int i = 1; i <= n; i++) { // 遍历背包 + for (int j = 1; j <= m; j++) { // 遍历物品 if (i - j >= 0) dp[i] += dp[i - j]; } } diff --git "a/problems/0112.\350\267\257\345\276\204\346\200\273\345\222\214.md" "b/problems/0112.\350\267\257\345\276\204\346\200\273\345\222\214.md" index be03f719e1..f1ce7637ba 100644 --- "a/problems/0112.\350\267\257\345\276\204\346\200\273\345\222\214.md" +++ "b/problems/0112.\350\267\257\345\276\204\346\200\273\345\222\214.md" @@ -1511,6 +1511,17 @@ impl Solution { } } +``` +### C# +```C# +// 0112.路径总和 +// 递归 +public bool HasPathSum(TreeNode root, int targetSum) +{ + if (root == null) return false; + if (root.left == null && root.right == null && targetSum == root.val) return true; + return HasPathSum(root.left, targetSum - root.val) || HasPathSum(root.right, targetSum - root.val); +} ```

diff --git "a/problems/0257.\344\272\214\345\217\211\346\240\221\347\232\204\346\211\200\346\234\211\350\267\257\345\276\204.md" "b/problems/0257.\344\272\214\345\217\211\346\240\221\347\232\204\346\211\200\346\234\211\350\267\257\345\276\204.md" index 44c0fd85e3..9ba165c798 100644 --- "a/problems/0257.\344\272\214\345\217\211\346\240\221\347\232\204\346\211\200\346\234\211\350\267\257\345\276\204.md" +++ "b/problems/0257.\344\272\214\345\217\211\346\240\221\347\232\204\346\211\200\346\234\211\350\267\257\345\276\204.md" @@ -900,6 +900,43 @@ impl Solution { } } ``` +### C# +```C# +public IList BinaryTreePaths(TreeNode root) +{ + List path = new(); + List res = new(); + if (root == null) return res; + Traversal(root, path, res); + return res; +} +public void Traversal(TreeNode node, List path, List res) +{ + path.Add(node.val); + if (node.left == null && node.right == null) + { + string sPath = ""; + for (int i = 0; i < path.Count - 1; i++) + { + sPath += path[i].ToString(); + sPath += "->"; + } + sPath += path[path.Count - 1].ToString(); + res.Add(sPath); + return; + } + if (node.left != null) + { + Traversal(node.left, path, res); + path.RemoveAt(path.Count-1); + } + if (node.right != null) + { + Traversal(node.right, path, res); + path.RemoveAt(path.Count-1); + } +} +```

diff --git "a/problems/0404.\345\267\246\345\217\266\345\255\220\344\271\213\345\222\214.md" "b/problems/0404.\345\267\246\345\217\266\345\255\220\344\271\213\345\222\214.md" index c1ad602d5f..6dfcc886bc 100644 --- "a/problems/0404.\345\267\246\345\217\266\345\255\220\344\271\213\345\222\214.md" +++ "b/problems/0404.\345\267\246\345\217\266\345\255\220\344\271\213\345\222\214.md" @@ -651,6 +651,23 @@ impl Solution { } } ``` +### C# +```C# +// 递归 +public int SumOfLeftLeaves(TreeNode root) +{ + if (root == null) return 0; + + int leftValue = SumOfLeftLeaves(root.left); + if (root.left != null && root.left.left == null && root.left.right == null) + { + leftValue += root.left.val; + } + int rightValue = SumOfLeftLeaves(root.right); + return leftValue + rightValue; + +} +```

diff --git "a/problems/0513.\346\211\276\346\240\221\345\267\246\344\270\213\350\247\222\347\232\204\345\200\274.md" "b/problems/0513.\346\211\276\346\240\221\345\267\246\344\270\213\350\247\222\347\232\204\345\200\274.md" index 7ef934cc88..0e2f426633 100644 --- "a/problems/0513.\346\211\276\346\240\221\345\267\246\344\270\213\350\247\222\347\232\204\345\200\274.md" +++ "b/problems/0513.\346\211\276\346\240\221\345\267\246\344\270\213\350\247\222\347\232\204\345\200\274.md" @@ -684,6 +684,38 @@ impl Solution { } } ``` +### C# +```C# +//递归 +int maxDepth = -1; +int res = 0; +public int FindBottomLeftValue(TreeNode root) +{ + Traversal(root, 0); + return res; +} +public void Traversal(TreeNode root, int depth) +{ + if (root.left == null && root.right == null) + { + if (depth > maxDepth) + { + maxDepth = depth; + res = root.val; + } + return; + } + if (root.left != null) + { + Traversal(root.left, depth + 1); + } + if (root.right != null) + { + Traversal(root.right, depth + 1); + } + return; +} +```

diff --git "a/problems/kama53.\345\257\273\345\256\235.md" "b/problems/kama53.\345\257\273\345\256\235.md" new file mode 100644 index 0000000000..b52ac374be --- /dev/null +++ "b/problems/kama53.\345\257\273\345\256\235.md" @@ -0,0 +1,155 @@ + + +如果你的图相对较小且比较密集,而且你更注重简单性和空间效率,数组实现可能更合适。 + +如果你的图规模较大,尤其是在稀疏图中,而且你更注重时间效率和通用性,优先级队列实现可能更合适。 + +其关键 在于弄清楚 minDist 的定义 + +```CPP + +#include +#include +#include +#include + +using namespace std; + +// 定义图的邻接矩阵表示 +const int INF = INT_MAX; // 表示无穷大 +typedef vector> Graph; + +// 使用Prim算法找到最小生成树 +void primMST(const Graph& graph, int startVertex) { + int V = graph.size(); + + // 存储顶点是否在最小生成树中 + vector inMST(V, false); + + // 存储最小生成树的边权重 + vector key(V, INF); + + // 优先队列,存储边权重和目标顶点 + priority_queue, vector>, greater>> pq; + + // 初始顶点的权重设为0,加入优先队列 + key[startVertex] = 0; + pq.push({0, startVertex}); + + while (!pq.empty()) { + // 从优先队列中取出权重最小的边 + int u = pq.top().second; + pq.pop(); + + // 将顶点u标记为在最小生成树中 + inMST[u] = true; + + // 遍历u的所有邻居 + for (int v = 0; v < V; ++v) { + // 如果v未在最小生成树中,且u到v的权重小于v的当前权重 + if (!inMST[v] && graph[u][v] < key[v]) { + // 更新v的权重为u到v的权重 + key[v] = graph[u][v]; + // 将(u, v)添加到最小生成树 + pq.push({key[v], v}); + } + } + } + + // 输出最小生成树的边 + cout << "Edges in the Minimum Spanning Tree:\n"; + for (int i = 1; i < V; ++i) { + cout << i << " - " << key[i] << " - " << i << "\n"; + } +} + +int main() { + // 例子:无向图的邻接矩阵表示 + Graph graph = { + {0, 2, 0, 6, 0}, + {2, 0, 3, 8, 5}, + {0, 3, 0, 0, 7}, + {6, 8, 0, 0, 9}, + {0, 5, 7, 9, 0} + }; + + // 从顶点0开始运行Prim算法 + primMST(graph, 0); + + return 0; +} +``` + + +```CPP +#include +#include +#include + +using namespace std; + +// 定义图的邻接矩阵表示 +const int INF = INT_MAX; // 表示无穷大 +typedef vector> Graph; + +// 使用Prim算法找到最小生成树 +void primMST(const Graph& graph, int startVertex) { + int V = graph.size(); + + // 存储顶点是否在最小生成树中 + vector inMST(V, false); + + // 存储每个顶点的权重 + vector key(V, INF); + + // 初始化起始顶点的权重为0 + key[startVertex] = 0; + + // 存储最小生成树的边权重 + vector parent(V, -1); + + // 构建最小生成树 + for (int count = 0; count < V - 1; ++count) { + // 从未在最小生成树中的顶点中找到权重最小的顶点 + int u = -1; + for (int v = 0; v < V; ++v) { + if (!inMST[v] && (u == -1 || key[v] < key[u])) { + u = v; + } + } + + // 将顶点u标记为在最小生成树中 + inMST[u] = true; + + // 更新u的邻居的权重和父节点 + for (int v = 0; v < V; ++v) { + if (graph[u][v] != 0 && !inMST[v] && graph[u][v] < key[v]) { + key[v] = graph[u][v]; + parent[v] = u; + } + } + } + + // 输出最小生成树的边 + cout << "Edges in the Minimum Spanning Tree:\n"; + for (int i = 1; i < V; ++i) { + cout << parent[i] << " - " << key[i] << " - " << i << "\n"; + } +} + +int main() { + // 例子:无向图的邻接矩阵表示 + Graph graph = { + {0, 2, 0, 6, 0}, + {2, 0, 3, 8, 5}, + {0, 3, 0, 0, 7}, + {6, 8, 0, 0, 9}, + {0, 5, 7, 9, 0} + }; + + // 从顶点0开始运行Prim算法 + primMST(graph, 0); + + return 0; +} +``` diff --git "a/problems/\345\223\210\345\270\214\350\241\250\347\220\206\350\256\272\345\237\272\347\241\200.md" "b/problems/\345\223\210\345\270\214\350\241\250\347\220\206\350\256\272\345\237\272\347\241\200.md" index 3055875a11..e426c65791 100644 --- "a/problems/\345\223\210\345\270\214\350\241\250\347\220\206\350\256\272\345\237\272\347\241\200.md" +++ "b/problems/\345\223\210\345\270\214\350\241\250\347\220\206\350\256\272\345\237\272\347\241\200.md" @@ -42,7 +42,7 @@ 如果hashCode得到的数值大于 哈希表的大小了,也就是大于tableSize了,怎么办呢? -此时为了保证映射出来的索引数值都落在哈希表上,我们会在再次对数值做一个取模的操作,就要我们就保证了学生姓名一定可以映射到哈希表上了。 +此时为了保证映射出来的索引数值都落在哈希表上,我们会在再次对数值做一个取模的操作,这样我们就保证了学生姓名一定可以映射到哈希表上了。 此时问题又来了,哈希表我们刚刚说过,就是一个数组。 diff --git "a/problems/\345\233\276\350\256\272\345\271\266\346\237\245\351\233\206\347\220\206\350\256\272\345\237\272\347\241\200.md" "b/problems/\345\233\276\350\256\272\345\271\266\346\237\245\351\233\206\347\220\206\350\256\272\345\237\272\347\241\200.md" index 2c14f49037..347bf58f13 100644 --- "a/problems/\345\233\276\350\256\272\345\271\266\346\237\245\351\233\206\347\220\206\350\256\272\345\237\272\347\241\200.md" +++ "b/problems/\345\233\276\350\256\272\345\271\266\346\237\245\351\233\206\347\220\206\350\256\272\345\237\272\347\241\200.md" @@ -274,27 +274,53 @@ join(3, 2); 通过以上讲解之后,我在带大家一步一步去画一下,并查集内部数据连接方式。 -注意:为了让录友们了解基础并查集的操作,不至于混乱,**以下模拟过程中不考虑路径压缩的过程**,了解基础并查集操作后,路径压缩也很容易理解。 +1、`join(1, 8);` -我们先通过一些列的join操作,将两两元素分别放入同一个集合中。 +![](https://code-thinking-1253855093.file.myqcloud.com/pics/20231122112727.png) -```CPP -join(1, 8); -join(3, 8); -join(1, 7); -join(8, 5); -join(2, 9); -join(6, 2); -``` -此时我们生成的的有向图为: +2、`join(3, 8);` -![](https://code-thinking-1253855093.file.myqcloud.com/pics/20230910203210.png) +![](https://code-thinking-1253855093.file.myqcloud.com/pics/20231122113857.png) 有录友可能想,`join(3, 8)` 在图中为什么 将 元素1 连向元素 3 而不是将 元素 8 连向 元素 3 呢? 这一点 我在 「常见误区」标题下已经详细讲解了,因为在`join(int u, int v)`函数里 要分别对 u 和 v 寻根之后再进行关联。 +3、`join(1, 7);` + +![](https://code-thinking-1253855093.file.myqcloud.com/pics/20231122114108.png) + + +4、`join(8, 5);` + +![](https://code-thinking-1253855093.file.myqcloud.com/pics/20231122114847.png) + +这里8的根是3,那么 5 应该指向 8 的根 3,这里的原因,我们在上面「常见误区」已经讲过了。 但 为什么 图中 8 又直接指向了 3 了呢? + +**因为路经压缩了** + +即如下代码在寻找跟的过程中,会有路径压缩,减少 下次查询的路径长度。 + +``` +// 并查集里寻根的过程 +int find(int u) { + return u == father[u] ? u : father[u] = find(father[u]); // 路径压缩 +} +``` + +5、`join(2, 9);` + +![](https://code-thinking-1253855093.file.myqcloud.com/pics/20231122115000.png) + +6、`join(6, 9);` + +![](https://code-thinking-1253855093.file.myqcloud.com/pics/20231122115404.png) + +这里为什么是 2 指向了 6,因为 9的根为 2,所以用2指向6。 + + + 大家看懂这个有向图后,相信应该知道如下函数的返回值了。 ```CPP @@ -309,6 +335,8 @@ true false ``` + + ## 拓展