From 183fe44ae0d0569f39ab525b57877d844e9d3823 Mon Sep 17 00:00:00 2001 From: Zhihan Li <54661071+zhihali@users.noreply.github.com> Date: Tue, 24 Sep 2024 16:09:20 +0100 Subject: [PATCH 01/24] =?UTF-8?q?Update=200134.=E5=8A=A0=E6=B2=B9=E7=AB=99?= =?UTF-8?q?.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0134.加油站.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/problems/0134.加油站.md b/problems/0134.加油站.md index 7ac9f0f9..5cf50b3e 100644 --- a/problems/0134.加油站.md +++ b/problems/0134.加油站.md @@ -158,7 +158,7 @@ i从0开始累加rest[i],和记为curSum,一旦curSum小于零,说明[0, i 如果 curSum<0 说明 区间和1 + 区间和2 < 0, 那么 假设从上图中的位置开始计数curSum不会小于0的话,就是 区间和2>0。 -区间和1 + 区间和2 < 0 同时 区间和2>0,只能说明区间和1 < 0, 那么就会从假设的箭头初就开始从新选择其实位置了。 +区间和1 + 区间和2 < 0 同时 区间和2>0,只能说明区间和1 < 0, 那么就会从假设的箭头初就开始从新选择起始位置了。 **那么局部最优:当前累加rest[i]的和curSum一旦小于0,起始位置至少要是i+1,因为从i之前开始一定不行。全局最优:找到可以跑一圈的起始位置**。 From 779ff9dd08a4b18d0aa8e077fcdab5e821662c08 Mon Sep 17 00:00:00 2001 From: suinming <0223314338aa@gmail.com> Date: Wed, 25 Sep 2024 12:35:34 +0800 Subject: [PATCH 02/24] =?UTF-8?q?feat:=2053.=20=E5=AF=BB=E5=AE=9D=E6=96=B0?= =?UTF-8?q?=E5=A2=9Ejs=E7=AE=97=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/kamacoder/0053.寻宝-prim.md | 49 ++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/problems/kamacoder/0053.寻宝-prim.md b/problems/kamacoder/0053.寻宝-prim.md index c71624b5..a8dad4cb 100644 --- a/problems/kamacoder/0053.寻宝-prim.md +++ b/problems/kamacoder/0053.寻宝-prim.md @@ -693,6 +693,55 @@ if __name__ == "__main__": ### Rust ### Javascript +```js +function prim(v, edges) { + const grid = Array.from({ length: v + 1 }, () => new Array(v + 1).fill(10001)); // Fixed grid initialization + const minDist = new Array(v + 1).fill(10001) + const isInTree = new Array(v + 1).fill(false) + // 建構鄰接矩陣 + for(const [v1, v2, w] of edges) { + grid[v1][v2] = w + grid[v2][v1] = w + } + // prim 演算法 + for (let i = 1 ; i < v ; i++) { + let cur = -1 + let tempMinDist = Number.MAX_VALUE + // 1. 尋找距離生成樹最近的節點 + for (let j = 1 ; j < v + 1 ; j++) { + if (!isInTree[j] && minDist[j] < tempMinDist) { + tempMinDist = minDist[j] + cur = j + } + } + // 2. 將節點放入生成樹 + isInTree[cur] = true + // 3. 更新非生成樹節點與生成樹的最短距離 + for (let j = 1 ; j < v + 1 ; j++) { + if (!isInTree[j] && grid[cur][j] < minDist[j]) { + minDist[j] = grid[cur][j] + } + } + } + console.log(minDist.slice(2).reduce((acc, cur) => acc + cur, 0)) +} + + +async function main() { + const rl = require('readline').createInterface({ input: process.stdin }) + const iter = rl[Symbol.asyncIterator]() + const readline = async () => (await iter.next()).value + const [v, e] = (await readline()).split(" ").map(Number) + const edges = [] + for (let i = 0 ; i < e ; i++) { + edges.push((await readline()).split(" ").map(Number)) + } + prim(v, edges) +} + + +main() +``` ### TypeScript From 9e66f2232363c66f1c466329b518fc2d8c6525c5 Mon Sep 17 00:00:00 2001 From: suinming <0223314338aa@gmail.com> Date: Wed, 25 Sep 2024 14:57:21 +0800 Subject: [PATCH 03/24] =?UTF-8?q?feat:=2053.=20=E5=AF=BB=E5=AE=9D=E6=96=B0?= =?UTF-8?q?=E5=A2=9Ekruskal=20js=E8=A7=A3=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/kamacoder/0053.寻宝-Kruskal.md | 56 +++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/problems/kamacoder/0053.寻宝-Kruskal.md b/problems/kamacoder/0053.寻宝-Kruskal.md index cb24fd17..6a227985 100644 --- a/problems/kamacoder/0053.寻宝-Kruskal.md +++ b/problems/kamacoder/0053.寻宝-Kruskal.md @@ -549,6 +549,62 @@ if __name__ == "__main__": ### Javascript +```js +function kruskal(v, edges) { + const father = Array.from({ length: v + 1 }, (_, i) => i) + + function find(u){ + if (u === father[u]) { + return u + } else { + father[u] = find(father[u]) + return father[u] + } + + } + + function isSame(u, v) { + let s = find(u) + let t = find(v) + return s === t + } + + function join(u, v) { + let s = find(u) + let t = find(v) + if (s !== t) { + father[s] = t + } + } + + edges.sort((a, b) => a[2] - b[2]) + let result = 0 + for (const [v1, v2, w] of edges) { + if (!isSame(v1, v2)) { + result += w + join(v1 ,v2) + } + } + console.log(result) +} + + +async function main() { + const rl = require('readline').createInterface({ input: process.stdin }) + const iter = rl[Symbol.asyncIterator]() + const readline = async () => (await iter.next()).value + const [v, e] = (await readline()).split(" ").map(Number) + const edges = [] + for (let i = 0 ; i < e ; i++) { + edges.push((await readline()).split(" ").map(Number)) + } + kruskal(v, edges) +} + + +main() +``` + ### TypeScript ### PhP From 13a4234fce501cf300974d4f28f7728c0f91e64e Mon Sep 17 00:00:00 2001 From: xiaodaoshou <1035011225@qq.com> Date: Wed, 25 Sep 2024 20:50:05 +0800 Subject: [PATCH 04/24] =?UTF-8?q?0005=E6=9C=80=E9=95=BF=E5=9B=9E=E6=96=87?= =?UTF-8?q?=E5=AD=90=E4=B8=B2=20Manacher=E7=AE=97=E6=B3=95C++=E7=89=88?= =?UTF-8?q?=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0005.最长回文子串.md | 54 +++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/problems/0005.最长回文子串.md b/problems/0005.最长回文子串.md index a13daf1e..b3d3b938 100644 --- a/problems/0005.最长回文子串.md +++ b/problems/0005.最长回文子串.md @@ -256,7 +256,60 @@ public: * 时间复杂度:O(n^2) * 空间复杂度:O(1) +### Manacher 算法 +Manacher 算法的关键在于高效利用回文的对称性,通过插入分隔符和维护中心、边界等信息,在线性时间内找到最长回文子串。这种方法避免了重复计算,是处理回文问题的最优解。 + +```c++ +//Manacher 算法 +class Solution { +public: + string longestPalindrome(string s) { + // 预处理字符串,在每个字符之间插入 '#' + string t = "#"; + for (char c : s) { + t += c; // 添加字符 + t += '#';// 添加分隔符 + } + int n = t.size();// 新字符串的长度 + vector p(n, 0);// p[i] 表示以 t[i] 为中心的回文半径 + int center = 0, right = 0;// 当前回文的中心和右边界 + + + // 遍历预处理后的字符串 + for (int i = 0; i < n; i++) { + // 如果当前索引在右边界内,利用对称性初始化 p[i] + if (i < right) { + p[i] = min(right - i, p[2 * center - i]); + } + // 尝试扩展回文 + while (i - p[i] - 1 >= 0 && i + p[i] + 1 < n && t[i - p[i] - 1] == t[i + p[i] + 1]) { + p[i]++;// 增加回文半径 + } + // 如果当前回文扩展超出右边界,更新中心和右边界 + if (i + p[i] > right) { + center = i;// 更新中心 + right = i + p[i];// 更新右边界 + } + } + // 找到最大回文半径和对应的中心 + int maxLen = 0, centerIndex = 0; + for (int i = 0; i < n; i++) { + if (p[i] > maxLen) { + maxLen = p[i];// 更新最大回文长度 + centerIndex = i;// 更新中心索引 + } + } + // 计算原字符串中回文子串的起始位置并返回 + return s.substr((centerIndex - maxLen) / 2, maxLen); + } +}; +``` + + + +* 时间复杂度:O(n) +* 空间复杂度:O(n) ## 其他语言版本 @@ -682,3 +735,4 @@ public class Solution { + From 1b08a8e5b5b1cb83ca55f2d42391791387f293dd Mon Sep 17 00:00:00 2001 From: suinming <0223314338aa@gmail.com> Date: Thu, 26 Sep 2024 12:56:42 +0800 Subject: [PATCH 05/24] =?UTF-8?q?feat:=2047.=20=E5=8F=82=E5=8A=A0=E7=A7=91?= =?UTF-8?q?=E5=AD=A6=E5=A4=A7=E4=BC=9A=E6=96=B0=E5=A2=9Ejs=E8=A7=A3?= =?UTF-8?q?=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kamacoder/0047.参会dijkstra朴素.md | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/problems/kamacoder/0047.参会dijkstra朴素.md b/problems/kamacoder/0047.参会dijkstra朴素.md index c0a490b3..465ad16d 100644 --- a/problems/kamacoder/0047.参会dijkstra朴素.md +++ b/problems/kamacoder/0047.参会dijkstra朴素.md @@ -869,6 +869,65 @@ if __name__ == "__main__": ### Javascript +```js +function dijkstra(grid, start, end) { + const visited = Array.from({length: end + 1}, () => false) + const minDist = Array.from({length: end + 1}, () => Number.MAX_VALUE) + minDist[start] = 0 + + for (let i = 1 ; i < end + 1 ; i++) { + let cur = -1 + let tempMinDist = Number.MAX_VALUE + // 1. 找尋與起始點距離最近且未被訪的節點 + for (let j = 1 ; j < end + 1 ; j++) { + if (!visited[j] && minDist[j] < tempMinDist) { + cur = j + tempMinDist = minDist[j] + } + } + if (cur === -1) break; + + // 2. 更新節點狀態為已拜訪 + visited[cur] = true + + // 3. 更新未拜訪節點與起始點的最短距離 + for (let j = 1 ; j < end + 1 ; j++) { + if(!visited[j] && grid[cur][j] != Number.MAX_VALUE + && grid[cur][j] + minDist[cur] < minDist[j] + ) { + minDist[j] = grid[cur][j] + minDist[cur] + } + } + } + + return minDist[end] === Number.MAX_VALUE ? -1 : minDist[end] +} + + +async function main() { + // 輸入 + const rl = require('readline').createInterface({ input: process.stdin }) + const iter = rl[Symbol.asyncIterator]() + const readline = async () => (await iter.next()).value + const [n, m] = (await readline()).split(" ").map(Number) + const grid = Array.from({length: n + 1}, + () => Array.from({length:n + 1}, () => Number.MAX_VALUE)) + for (let i = 0 ; i < m ; i++) { + const [s, e, w] = (await readline()).split(" ").map(Number) + grid[s][e] = w + } + + // dijkstra + const result = dijkstra(grid, 1, n) + + // 輸出 + console.log(result) +} + + +main() +``` + ### TypeScript ### PhP From 4c37cedc435eca094a98d9c201b43663605264d7 Mon Sep 17 00:00:00 2001 From: MAX <61301100+miaoxu404@users.noreply.github.com> Date: Thu, 26 Sep 2024 15:07:38 +0800 Subject: [PATCH 06/24] =?UTF-8?q?Update=200513.=E6=89=BE=E6=A0=91=E5=B7=A6?= =?UTF-8?q?=E4=B8=8B=E8=A7=92=E7=9A=84=E5=80=BC.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The term maxLen has ambiguity and does not align clearly with both the code and the problem statement. I propose changing it to maxDepth for improved clarity and consistency. --- problems/0513.找树左下角的值.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/problems/0513.找树左下角的值.md b/problems/0513.找树左下角的值.md index d69ceb6f..c7446726 100644 --- a/problems/0513.找树左下角的值.md +++ b/problems/0513.找树左下角的值.md @@ -55,7 +55,7 @@ 参数必须有要遍历的树的根节点,还有就是一个int型的变量用来记录最长深度。 这里就不需要返回值了,所以递归函数的返回类型为void。 -本题还需要类里的两个全局变量,maxLen用来记录最大深度,result记录最大深度最左节点的数值。 +本题还需要类里的两个全局变量,maxDepth用来记录最大深度,result记录最大深度最左节点的数值。 代码如下: From 53a4a17b8c518b6e27166b3b9b60de44fdf9b39a Mon Sep 17 00:00:00 2001 From: Camille <59353274+Camille0512@users.noreply.github.com> Date: Thu, 26 Sep 2024 23:06:45 +0800 Subject: [PATCH 07/24] =?UTF-8?q?Update=200099.=E5=B2=9B=E5=B1=BF=E7=9A=84?= =?UTF-8?q?=E6=95=B0=E9=87=8F=E5=B9=BF=E6=90=9C.md:=20Add=20Scala=20script?= =?UTF-8?q?=20for=20the=20counting=20island=20puzzle=20using=20BFS=20algo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kamacoder/0099.岛屿的数量广搜.md | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/problems/kamacoder/0099.岛屿的数量广搜.md b/problems/kamacoder/0099.岛屿的数量广搜.md index 30475753..9d31c922 100644 --- a/problems/kamacoder/0099.岛屿的数量广搜.md +++ b/problems/kamacoder/0099.岛屿的数量广搜.md @@ -499,6 +499,55 @@ main(); ### Swift ### Scala +```scala +import scala.collection.mutable.Queue +import util.control.Breaks._ + +// Dev on LeetCode: https://leetcode.cn/problems/number-of-islands/description/ +object Solution { + def numIslands(grid: Array[Array[Char]]): Int = { + val row = grid.length + val col = grid(0).length + val dir = List((-1,0), (0,-1), (1,0), (0,1)) // 四个方向 + var visited = Array.fill(row)(Array.fill(col)(false)) + var counter = 0 + var que = Queue.empty[Tuple2[Int, Int]] + + (0 until row).map{ r => + (0 until col).map{ c => + breakable { + if (!visited(r)(c) && grid(r)(c) == '1') { + que.enqueue((r, c)) + visited(r)(c) // 只要加入队列,立刻标记 + } else break // 不是岛屿不进入queue,也不记录 + + while (!que.isEmpty) { + val cur = que.head + que.dequeue() + val x = cur(0) + val y = cur(1) + dir.map{ d => + val nextX = x + d(0) + val nextY = y + d(1) + breakable { + // 越界就跳过 + if (nextX < 0 || nextX >= row || nextY < 0 || nextY >= col) break + if (!visited(nextX)(nextY) && grid(nextX)(nextY) == '1') { + visited(nextX)(nextY) = true // 只要加入队列,立刻标记 + que.enqueue((nextX, nextY)) + } + } + } + } + counter = counter + 1 // 找完一个岛屿后记录一下 + } + } + } + + counter + } +} +``` ### C# From d0f6653a6f371ee22130116470030bd35b925212 Mon Sep 17 00:00:00 2001 From: MAX <61301100+miaoxu404@users.noreply.github.com> Date: Fri, 27 Sep 2024 11:51:01 +0800 Subject: [PATCH 08/24] =?UTF-8?q?Update=200112.=E8=B7=AF=E5=BE=84=E6=80=BB?= =?UTF-8?q?=E5=92=8C.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit it's important to avoid using reserved keywords as variable names. so i suggest changing "sum" to "targetSum" In order to maintain consistency with the original LeetCode problem, the term "TreeNode" can be replaced with "Optional[TreeNode]". --- problems/0112.路径总和.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/problems/0112.路径总和.md b/problems/0112.路径总和.md index 6709a2fb..e6ccc6ae 100644 --- a/problems/0112.路径总和.md +++ b/problems/0112.路径总和.md @@ -564,10 +564,10 @@ class Solution: return False - def hasPathSum(self, root: TreeNode, sum: int) -> bool: + def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool: if root is None: return False - return self.traversal(root, sum - root.val) + return self.traversal(root, targetSum - root.val) ``` (版本二) 递归 + 精简 @@ -579,12 +579,12 @@ class Solution: # self.left = left # self.right = right class Solution: - def hasPathSum(self, root: TreeNode, sum: int) -> bool: + def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool: if not root: return False - if not root.left and not root.right and sum == root.val: + if not root.left and not root.right and targetSum == root.val: return True - return self.hasPathSum(root.left, sum - root.val) or self.hasPathSum(root.right, sum - root.val) + return self.hasPathSum(root.left, targetSum - root.val) or self.hasPathSum(root.right, targetSum - root.val) ``` (版本三) 迭代 @@ -596,7 +596,7 @@ class Solution: # self.left = left # self.right = right class Solution: - def hasPathSum(self, root: TreeNode, sum: int) -> bool: + def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool: if not root: return False # 此时栈里要放的是pair<节点指针,路径数值> @@ -659,13 +659,13 @@ class Solution: return - def pathSum(self, root: TreeNode, sum: int) -> List[List[int]]: + def pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]: self.result.clear() self.path.clear() if not root: return self.result self.path.append(root.val) # 把根节点放进路径 - self.traversal(root, sum - root.val) + self.traversal(root, targetSum - root.val) return self.result ``` @@ -678,7 +678,7 @@ class Solution: # self.left = left # self.right = right class Solution: - def pathSum(self, root: TreeNode, targetSum: int) -> List[List[int]]: + def pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]: result = [] self.traversal(root, targetSum, [], result) @@ -703,7 +703,7 @@ class Solution: # self.left = left # self.right = right class Solution: - def pathSum(self, root: TreeNode, targetSum: int) -> List[List[int]]: + def pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]: if not root: return [] stack = [(root, [root.val])] From 8ff94842609eee048ec78b709a20a82339c3c093 Mon Sep 17 00:00:00 2001 From: suinming <0223314338aa@gmail.com> Date: Fri, 27 Sep 2024 15:20:59 +0800 Subject: [PATCH 09/24] =?UTF-8?q?feat:=2094.=20=E5=9F=8E=E5=B8=82=E9=97=B4?= =?UTF-8?q?=E8=B4=A7=E7=89=A9=E8=BF=90=E8=BE=93=20I=20=E6=96=B0=E5=A2=9Ejs?= =?UTF-8?q?=E7=AE=97=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kamacoder/0094.城市间货物运输I.md | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/problems/kamacoder/0094.城市间货物运输I.md b/problems/kamacoder/0094.城市间货物运输I.md index 3737fe01..9021e0fe 100644 --- a/problems/kamacoder/0094.城市间货物运输I.md +++ b/problems/kamacoder/0094.城市间货物运输I.md @@ -485,6 +485,45 @@ if __name__ == "__main__": ### Javascript +```js +async function main() { + // 輸入 + const rl = require('readline').createInterface({ input: process.stdin }) + const iter = rl[Symbol.asyncIterator]() + const readline = async () => (await iter.next()).value + const [n, m] = (await readline()).split(" ").map(Number) + const edges = [] + for (let i = 0 ; i < m ; i++) { + edges.push((await readline()).split(" ").map(Number)) + } + const minDist = Array.from({length: n + 1}, () => Number.MAX_VALUE) + // 起始點 + minDist[1] = 0 + + for (let i = 1 ; i < n ; i++) { + let update = false + for (const [src, desc, w] of edges) { + if (minDist[src] !== Number.MAX_VALUE && minDist[src] + w < minDist[desc]) { + minDist[desc] = minDist[src] + w + update = true + } + } + if (!update) { + break; + } + } + + // 輸出 + if (minDist[n] === Number.MAX_VALUE) { + console.log('unconnected') + } else { + console.log(minDist[n]) + } +} + +main() +``` + ### TypeScript ### PhP From c55a05a496fdb75c1f38fe49a060fa3985565342 Mon Sep 17 00:00:00 2001 From: suinming <0223314338aa@gmail.com> Date: Fri, 27 Sep 2024 15:59:22 +0800 Subject: [PATCH 10/24] =?UTF-8?q?feat:=20=2094.=20=E5=9F=8E=E5=B8=82?= =?UTF-8?q?=E9=97=B4=E8=B4=A7=E7=89=A9=E8=BF=90=E8=BE=93=20I=20SPEA?= =?UTF-8?q?=E6=96=B0=E5=A2=9Ejs=E7=AE=97=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../0094.城市间货物运输I-SPFA.md | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/problems/kamacoder/0094.城市间货物运输I-SPFA.md b/problems/kamacoder/0094.城市间货物运输I-SPFA.md index b3f42bf8..9ba92599 100644 --- a/problems/kamacoder/0094.城市间货物运输I-SPFA.md +++ b/problems/kamacoder/0094.城市间货物运输I-SPFA.md @@ -464,6 +464,60 @@ if __name__ == "__main__": ### Javascript +```js +async function main() { + // 輸入 + const rl = require('readline').createInterface({ input: process.stdin }) + const iter = rl[Symbol.asyncIterator]() + const readline = async () => (await iter.next()).value + const [n, m] = (await readline()).split(" ").map(Number) + const grid = {} + for (let i = 0 ; i < m ; i++) { + const [src, desc, w] = (await readline()).split(" ").map(Number) + if (grid.hasOwnProperty(src)) { + grid[src].push([desc, w]) + } else { + grid[src] = [[desc, w]] + } + } + const minDist = Array.from({length: n + 1}, () => Number.MAX_VALUE) + + // 起始點 + minDist[1] = 0 + + const q = [1] + const visited = Array.from({length: n + 1}, () => false) + + while (q.length) { + const src = q.shift() + const neighbors = grid[src] + visited[src] = false + if (neighbors) { + for (const [desc, w] of neighbors) { + if (minDist[src] !== Number.MAX_VALUE + && minDist[src] + w < minDist[desc]) { + minDist[desc] = minDist[src] + w + if (!visited[desc]) { + q.push(desc) + visited[desc] = true + } + + } + } + } + } + + // 輸出 + if (minDist[n] === Number.MAX_VALUE) { + console.log('unconnected') + } else { + console.log(minDist[n]) + } +} + +main() +``` + ### TypeScript ### PhP From ecf70c6e57dc5d6e7583f9d362d5420f2d6dc74a Mon Sep 17 00:00:00 2001 From: suinming <0223314338aa@gmail.com> Date: Fri, 27 Sep 2024 19:43:51 +0800 Subject: [PATCH 11/24] =?UTF-8?q?feat:=2096.=20=E5=9F=8E=E5=B8=82=E9=97=B4?= =?UTF-8?q?=E8=B4=A7=E7=89=A9=E8=BF=90=E8=BE=93=20III=E5=A2=9E=E5=8A=A0pyt?= =?UTF-8?q?hon=E8=A7=A3=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../0096.城市间货物运输III.md | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/problems/kamacoder/0096.城市间货物运输III.md b/problems/kamacoder/0096.城市间货物运输III.md index dacd23d1..567a1d87 100644 --- a/problems/kamacoder/0096.城市间货物运输III.md +++ b/problems/kamacoder/0096.城市间货物运输III.md @@ -703,6 +703,42 @@ public class Main { ``` ### Python +```python +def main(): + # 輸入 + n, m = map(int, input().split()) + edges = list() + for _ in range(m): + edges.append(list(map(int, input().split() ))) + + start, end, k = map(int, input().split()) + min_dist = [float('inf') for _ in range(n + 1)] + min_dist[start] = 0 + + # 只能經過k個城市,所以從起始點到中間有(k + 1)個邊連接 + # 需要鬆弛(k + 1)次 + + for _ in range(k + 1): + update = False + min_dist_copy = min_dist.copy() + for src, desc, w in edges: + if (min_dist_copy[src] != float('inf') and + min_dist_copy[src] + w < min_dist[desc]): + min_dist[desc] = min_dist_copy[src] + w + update = True + if not update: + break + # 輸出 + if min_dist[end] == float('inf'): + print('unreachable') + else: + print(min_dist[end]) + + + +if __name__ == "__main__": + main() +``` ### Go From b32888260f0cb2f29314cf0c4d7d4dddb1f20f71 Mon Sep 17 00:00:00 2001 From: Ziyang Wen Date: Fri, 27 Sep 2024 21:17:44 +0800 Subject: [PATCH 12/24] =?UTF-8?q?0151python=E7=89=88=E6=9C=AC1=E5=88=A0?= =?UTF-8?q?=E9=99=A4=E5=86=97=E4=BD=99=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0151.翻转字符串里的单词.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/problems/0151.翻转字符串里的单词.md b/problems/0151.翻转字符串里的单词.md index bf486bdc..9a0cbea4 100644 --- a/problems/0151.翻转字符串里的单词.md +++ b/problems/0151.翻转字符串里的单词.md @@ -440,11 +440,10 @@ class Solution { ```Python class Solution: def reverseWords(self, s: str) -> str: - # 删除前后空白 - s = s.strip() # 反转整个字符串 s = s[::-1] # 将字符串拆分为单词,并反转每个单词 + # split()函数能够自动忽略多余的空白字符 s = ' '.join(word[::-1] for word in s.split()) return s @@ -1029,3 +1028,4 @@ public string ReverseWords(string s) { + From 0c29c3ed1edd5fcf5be9a8eb6dcba6fc25fb569b Mon Sep 17 00:00:00 2001 From: Ziyang Wen Date: Fri, 27 Sep 2024 21:23:03 +0800 Subject: [PATCH 13/24] =?UTF-8?q?0541.=E5=8F=8D=E8=BD=AC=E5=AD=97=E7=AC=A6?= =?UTF-8?q?=E4=B8=B2II=20=E6=80=9D=E8=B7=AF=20=E5=88=A0=E9=99=A4=E4=BA=86?= =?UTF-8?q?=E5=A4=9A=E4=BD=99=E7=9A=84=E2=80=9C=E5=9C=A8=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0541.反转字符串II.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/problems/0541.反转字符串II.md b/problems/0541.反转字符串II.md index 3e304fab..5e75d3c3 100644 --- a/problems/0541.反转字符串II.md +++ b/problems/0541.反转字符串II.md @@ -37,7 +37,7 @@ 因为要找的也就是每2 * k 区间的起点,这样写,程序会高效很多。 -**所以当需要固定规律一段一段去处理字符串的时候,要想想在在for循环的表达式上做做文章。** +**所以当需要固定规律一段一段去处理字符串的时候,要想想在for循环的表达式上做做文章。** 性能如下: @@ -505,3 +505,4 @@ impl Solution { + From 2173dd9e6430d8005df0781b4b05a9171208efc4 Mon Sep 17 00:00:00 2001 From: Ziyang Wen Date: Fri, 27 Sep 2024 21:26:55 +0800 Subject: [PATCH 14/24] =?UTF-8?q?0226.Python=E8=BF=AD=E4=BB=A3=E6=B3=95?= =?UTF-8?q?=E5=B9=BF=E5=BA=A6=E4=BC=98=E5=85=88=E9=81=8D=E5=8E=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0226.翻转二叉树.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/problems/0226.翻转二叉树.md b/problems/0226.翻转二叉树.md index e501b298..55dc3cbf 100644 --- a/problems/0226.翻转二叉树.md +++ b/problems/0226.翻转二叉树.md @@ -459,11 +459,10 @@ class Solution: queue = collections.deque([root]) while queue: - for i in range(len(queue)): - node = queue.popleft() - node.left, node.right = node.right, node.left - if node.left: queue.append(node.left) - if node.right: queue.append(node.right) + node = queue.popleft() + node.left, node.right = node.right, node.left + if node.left: queue.append(node.left) + if node.right: queue.append(node.right) return root ``` @@ -1033,4 +1032,3 @@ public TreeNode InvertTree(TreeNode root) { - From 9a4dab8f898c175559b121f455707eb82452196f Mon Sep 17 00:00:00 2001 From: Camille <59353274+Camille0512@users.noreply.github.com> Date: Fri, 27 Sep 2024 22:49:01 +0800 Subject: [PATCH 15/24] =?UTF-8?q?Update=200099.=E5=B2=9B=E5=B1=BF=E7=9A=84?= =?UTF-8?q?=E6=95=B0=E9=87=8F=E6=B7=B1=E6=90=9C.md=20Add=20Scala=20code=20?= =?UTF-8?q?to=20solve=20counting=20islands=20problem=20on=20LeetCode?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kamacoder/0099.岛屿的数量深搜.md | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/problems/kamacoder/0099.岛屿的数量深搜.md b/problems/kamacoder/0099.岛屿的数量深搜.md index 6ac7ba3b..da1c0739 100644 --- a/problems/kamacoder/0099.岛屿的数量深搜.md +++ b/problems/kamacoder/0099.岛屿的数量深搜.md @@ -412,6 +412,46 @@ const dfs = (graph, visited, x, y) => { ### Swift ### Scala +```scala +import util.control.Breaks._ + +object Solution { + val dir = List((-1,0), (0,-1), (1,0), (0,1)) // 四个方向 + + def dfs(grid: Array[Array[Char]], visited: Array[Array[Boolean]], row: Int, col: Int): Unit = { + (0 until 4).map { x => + val nextR = row + dir(x)(0) + val nextC = col + dir(x)(1) + breakable { + if(nextR < 0 || nextR >= grid.length || nextC < 0 || nextC >= grid(0).length) break + if (!visited(nextR)(nextC) && grid(nextR)(nextC) == '1') { + visited(nextR)(nextC) = true // 经过就记录 + dfs(grid, visited, nextR, nextC) + } + } + } + } + + def numIslands(grid: Array[Array[Char]]): Int = { + val row = grid.length + val col = grid(0).length + var visited = Array.fill(row)(Array.fill(col)(false)) + var counter = 0 + + (0 until row).map{ r => + (0 until col).map{ c => + if (!visited(r)(c) && grid(r)(c) == '1') { + visited(r)(c) = true // 经过就记录 + dfs(grid, visited, r, c) + counter += 1 + } + } + } + + counter + } +} +``` ### C# From 2f58a7b043eeb19eff88c174366db1777a6fff66 Mon Sep 17 00:00:00 2001 From: DraculaJay <113758447+DraculaJay@users.noreply.github.com> Date: Sat, 28 Sep 2024 04:55:41 +0800 Subject: [PATCH 16/24] =?UTF-8?q?0053=20=E6=B7=BB=E5=8A=A0python=E5=8A=A8?= =?UTF-8?q?=E6=80=81=E8=A7=84=E5=88=92=E8=A7=A3=E6=B3=95=E5=92=8C=E5=8A=A8?= =?UTF-8?q?=E6=80=81=E8=A7=84=E5=88=92=E4=BC=98=E5=8C=96=E8=A7=A3=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0053.最大子序和.md | 36 ++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/problems/0053.最大子序和.md b/problems/0053.最大子序和.md index 551c39bf..50757564 100644 --- a/problems/0053.最大子序和.md +++ b/problems/0053.最大子序和.md @@ -229,6 +229,42 @@ class Solution: ``` + +动态规划 + +```python +class Solution: + def maxSubArray(self, nums): + if not nums: + return 0 + dp = [0] * len(nums) # dp[i]表示包括i之前的最大连续子序列和 + dp[0] = nums[0] + result = dp[0] + for i in range(1, len(nums)): + dp[i] = max(dp[i-1]+nums[i], nums[i]) # 状态转移公式 + if dp[i] > result: + result = dp[i] # result 保存dp[i]的最大值 + return result +``` + +动态规划优化 + +```python +class Solution: + def maxSubArray(self, nums: List[int]) -> int: + max_sum = float("-inf") # 初始化结果为负无穷大,方便比较取最大值 + current_sum = 0 # 初始化当前连续和 + + for num in nums: + + # 更新当前连续和 + # 如果原本的连续和加上当前数字之后没有当前数字大,说明原本的连续和是负数,那么就直接从当前数字开始重新计算连续和 + current_sum = max(current_sum+num, num) + max_sum = max(max_sum, current_sum) # 更新结果 + + return max_sum +``` + ### Go 贪心法 ```go From 0ea7587f72abd2c45cc711da696d1c580ddafa06 Mon Sep 17 00:00:00 2001 From: DraculaJay <113758447+DraculaJay@users.noreply.github.com> Date: Sat, 28 Sep 2024 05:04:22 +0800 Subject: [PATCH 17/24] =?UTF-8?q?0055=20=E8=B7=B3=E8=B7=83=E6=B8=B8?= =?UTF-8?q?=E6=88=8F=E6=B7=BB=E5=8A=A0python=20=E8=A7=A3=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0055.跳跃游戏.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/problems/0055.跳跃游戏.md b/problems/0055.跳跃游戏.md index 01fd9513..82b433d7 100644 --- a/problems/0055.跳跃游戏.md +++ b/problems/0055.跳跃游戏.md @@ -143,6 +143,23 @@ class Solution: return False ``` +```python +## 基于当前最远可到达位置判断 +class Solution: + def canJump(self, nums: List[int]) -> bool: + far = nums[0] + for i in range(len(nums)): + # 要考虑两个情况 + # 1. i <= far - 表示 当前位置i 可以到达 + # 2. i > far - 表示 当前位置i 无法到达 + if i > far: + return False + far = max(far, nums[i]+i) + # 如果循环正常结束,表示最后一个位置也可以到达,否则会在中途直接退出 + # 关键点在于,要想明白其实列表中的每个位置都是需要验证能否到达的 + return True +``` + ### Go ```go From 754d2d664d848a7f79b7b97347f9fcf27a03749b Mon Sep 17 00:00:00 2001 From: Zhihan Li <54661071+zhihali@users.noreply.github.com> Date: Sun, 29 Sep 2024 23:24:11 +0100 Subject: [PATCH 18/24] =?UTF-8?q?Update=200135.=E5=88=86=E5=8F=91=E7=B3=96?= =?UTF-8?q?=E6=9E=9C.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0135.分发糖果.md | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/problems/0135.分发糖果.md b/problems/0135.分发糖果.md index 6805857e..29eaa06d 100644 --- a/problems/0135.分发糖果.md +++ b/problems/0135.分发糖果.md @@ -177,21 +177,20 @@ class Solution { ```python class Solution: def candy(self, ratings: List[int]) -> int: - candyVec = [1] * len(ratings) + n = len(ratings) + candies = [1] * n - # 从前向后遍历,处理右侧比左侧评分高的情况 - for i in range(1, len(ratings)): + # Forward pass: handle cases where right rating is higher than left + for i in range(1, n): if ratings[i] > ratings[i - 1]: - candyVec[i] = candyVec[i - 1] + 1 + candies[i] = candies[i - 1] + 1 - # 从后向前遍历,处理左侧比右侧评分高的情况 - for i in range(len(ratings) - 2, -1, -1): + # Backward pass: handle cases where left rating is higher than right + for i in range(n - 2, -1, -1): if ratings[i] > ratings[i + 1]: - candyVec[i] = max(candyVec[i], candyVec[i + 1] + 1) + candies[i] = max(candies[i], candies[i + 1] + 1) - # 统计结果 - result = sum(candyVec) - return result + return sum(candies) ``` From fc004742e70956263fbfba9ca48c3b80d6aee845 Mon Sep 17 00:00:00 2001 From: "Ethan.Liu" Date: Sat, 5 Oct 2024 12:26:05 +0800 Subject: [PATCH 19/24] =?UTF-8?q?feat:=200977.=E6=9C=89=E5=BA=8F=E6=95=B0?= =?UTF-8?q?=E7=BB=84=E7=9A=84=E5=B9=B3=E6=96=B9=20python3=E5=8F=8C?= =?UTF-8?q?=E6=8C=87=E9=92=88=E4=B8=89=E6=AD=A5=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0977.有序数组的平方.md | 38 ++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/problems/0977.有序数组的平方.md b/problems/0977.有序数组的平方.md index effa9055..1a6604c2 100644 --- a/problems/0977.有序数组的平方.md +++ b/problems/0977.有序数组的平方.md @@ -100,6 +100,7 @@ public: ## 其他语言版本 ### Java: + 排序法 ```Java class Solution { @@ -209,6 +210,43 @@ class Solution: return new_list[::-1] ``` +```python3 +(双指针优化版本) 三步优化 + class Solution: + def sortedSquares(self, nums: List[int]) -> List[int]: + """ + 整体思想:有序数组的绝对值最大值永远在两头,比较两头,平方大的插到新数组的最后 + 优 化:1. 优化所有元素为非正或非负的情况 + 2. 头尾平方的大小比较直接将头尾相加与0进行比较即可 + 3. 新的平方排序数组的插入索引可以用倒序插入实现(针对for循环,while循环不适用) + """ + + # 特殊情况, 元素都非负(优化1) + if nums[0] >= 0: + return [num ** 2 for num in nums] # 按顺序平方即可 + # 最后一个非正,全负有序的 + if nums[-1] <= 0: + return [x ** 2 for x in nums[::-1]] # 倒序平方后的数组 + + # 一般情况, 有正有负 + i = 0 # 原数组头索引 + j = len(nums) - 1 # 原数组尾部索引 + new_nums = [0] * len(nums) # 新建一个等长数组用于保存排序后的结果 + # end_index = len(nums) - 1 # 新的排序数组(是新数组)尾插索引, 每次需要减一(优化3优化了) + + for end_index in range(len(nums)-1, -1, -1): # (优化3,倒序,不用单独创建变量) + # if nums[i] ** 2 >= nums[j] ** 2: + if nums[i] + nums[j] <= 0: # (优化2) + new_nums[end_index] = nums[i] ** 2 + i += 1 + # end_index -= 1 (优化3) + else: + new_nums[end_index] = nums[j] ** 2 + j -= 1 + # end_index -= 1 (优化3) + return new_nums +``` + ### Go: ```Go From 0a33a8d05c1c430bdb56d63a360e2de0d09b6ace Mon Sep 17 00:00:00 2001 From: Nomop <13098939400@163.com> Date: Sat, 5 Oct 2024 15:21:32 +0800 Subject: [PATCH 20/24] =?UTF-8?q?Update=200100.=E5=B2=9B=E5=B1=BF=E7=9A=84?= =?UTF-8?q?=E6=9C=80=E5=A4=A7=E9=9D=A2=E7=A7=AF.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 100.岛屿的最大面积新增Rust解法 --- .../kamacoder/0100.岛屿的最大面积.md | 138 ++++++++++++++++++ 1 file changed, 138 insertions(+) diff --git a/problems/kamacoder/0100.岛屿的最大面积.md b/problems/kamacoder/0100.岛屿的最大面积.md index 51bfc57f..50e40f3a 100644 --- a/problems/kamacoder/0100.岛屿的最大面积.md +++ b/problems/kamacoder/0100.岛屿的最大面积.md @@ -389,6 +389,144 @@ func main() { ### Rust +DFS + +``` rust +use std::io; +use std::cmp; + +// 定义四个方向 +const DIRECTIONS: [(i32, i32); 4] = [(0, 1), (1, 0), (-1, 0), (0, -1)]; + +fn dfs(grid: &Vec>, visited: &mut Vec>, x: usize, y: usize, count: &mut i32) { + if visited[x][y] || grid[x][y] == 0 { + return; // 终止条件:已访问或者遇到海水 + } + visited[x][y] = true; // 标记已访问 + *count += 1; + + for &(dx, dy) in DIRECTIONS.iter() { + let new_x = x as i32 + dx; + let new_y = y as i32 + dy; + + // 检查边界条件 + if new_x >= 0 && new_x < grid.len() as i32 && new_y >= 0 && new_y < grid[0].len() as i32 { + dfs(grid, visited, new_x as usize, new_y as usize, count); + } + } +} + +fn main() { + let mut input = String::new(); + + // 读取 n 和 m + io::stdin().read_line(&mut input); + let dims: Vec = input.trim().split_whitespace().map(|s| s.parse().unwrap()).collect(); + let (n, m) = (dims[0], dims[1]); + + // 读取 grid + let mut grid = vec![]; + for _ in 0..n { + input.clear(); + io::stdin().read_line(&mut input); + let row: Vec = input.trim().split_whitespace().map(|s| s.parse().unwrap()).collect(); + grid.push(row); + } + + // 初始化访问记录 + let mut visited = vec![vec![false; m]; n]; + let mut result = 0; + + // 遍历所有格子 + for i in 0..n { + for j in 0..m { + if !visited[i][j] && grid[i][j] == 1 { + let mut count = 0; + dfs(&grid, &mut visited, i, j, &mut count); + result = cmp::max(result, count); + } + } + } + + // 输出结果 + println!("{}", result); +} + +``` +BFS +```rust +use std::io; +use std::collections::VecDeque; + +// 定义四个方向 +const DIRECTIONS: [(i32, i32); 4] = [(0, 1), (1, 0), (-1, 0), (0, -1)]; + +fn bfs(grid: &Vec>, visited: &mut Vec>, x: usize, y: usize) -> i32 { + let mut count = 0; + let mut queue = VecDeque::new(); + queue.push_back((x, y)); + visited[x][y] = true; // 标记已访问 + + while let Some((cur_x, cur_y)) = queue.pop_front() { + count += 1; // 增加计数 + + for &(dx, dy) in DIRECTIONS.iter() { + let new_x = cur_x as i32 + dx; + let new_y = cur_y as i32 + dy; + + // 检查边界条件 + if new_x >= 0 && new_x < grid.len() as i32 && new_y >= 0 && new_y < grid[0].len() as i32 { + let new_x_usize = new_x as usize; + let new_y_usize = new_y as usize; + + // 如果未访问且是陆地,加入队列 + if !visited[new_x_usize][new_y_usize] && grid[new_x_usize][new_y_usize] == 1 { + visited[new_x_usize][new_y_usize] = true; // 标记已访问 + queue.push_back((new_x_usize, new_y_usize)); + } + } + } + } + + count +} + +fn main() { + let mut input = String::new(); + + // 读取 n 和 m + io::stdin().read_line(&mut input).expect("Failed to read line"); + let dims: Vec = input.trim().split_whitespace().map(|s| s.parse().unwrap()).collect(); + let (n, m) = (dims[0], dims[1]); + + // 读取 grid + let mut grid = vec![]; + for _ in 0..n { + input.clear(); + io::stdin().read_line(&mut input).expect("Failed to read line"); + let row: Vec = input.trim().split_whitespace().map(|s| s.parse().unwrap()).collect(); + grid.push(row); + } + + // 初始化访问记录 + let mut visited = vec![vec![false; m]; n]; + let mut result = 0; + + // 遍历所有格子 + for i in 0..n { + for j in 0..m { + if !visited[i][j] && grid[i][j] == 1 { + let count = bfs(&grid, &mut visited, i, j); + result = result.max(count); + } + } + } + + // 输出结果 + println!("{}", result); +} + +``` ### Javascript From a663089383732a56011c1b630c30635265c316a7 Mon Sep 17 00:00:00 2001 From: jjblaack Date: Sat, 5 Oct 2024 18:07:00 +0800 Subject: [PATCH 21/24] =?UTF-8?q?=E5=B2=9B=E5=B1=BF=E7=9A=84=E6=9C=80?= =?UTF-8?q?=E5=A4=A7=E9=9D=A2=E7=A7=AFjava=E5=AE=9E=E7=8E=B0=EF=BC=88dfs+b?= =?UTF-8?q?fs=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kamacoder/0100.岛屿的最大面积.md | 116 +++++++++++++++++- 1 file changed, 115 insertions(+), 1 deletion(-) diff --git a/problems/kamacoder/0100.岛屿的最大面积.md b/problems/kamacoder/0100.岛屿的最大面积.md index 51bfc57f..38b98d0e 100644 --- a/problems/kamacoder/0100.岛屿的最大面积.md +++ b/problems/kamacoder/0100.岛屿的最大面积.md @@ -223,7 +223,121 @@ public: ## 其他语言版本 ### Java - +DFS +```java +//这里的实现为主函数处理每个岛屿的第一块陆地 方式 +//所以是主函数直接置count为1,剩余的交给dfs来做。 +import java.util.*; +public class Main{ + static int[][] dir = {{0,-1}, {1,0}, {0,1}, {-1, 0}};//四个方向 + static int count = 0; + public static void dfs(boolean[][] visited, int x, int y, int[][] grid){ + for(int i = 0; i < 4; i++){ + int nextX = x + dir[i][0]; + int nextY = y + dir[i][1]; + if(nextX < 0 || nextY < 0 || nextY >= grid[0].length || nextX >= grid.length){ + continue; + } + if(!visited[nextX][nextY] && grid[nextX][nextY] == 1){ + count++; + visited[nextX][nextY] = true; + dfs(visited, nextX, nextY, grid); + } + } + } + public static void main(String[] args){ + Scanner in = new Scanner(System.in); + int n = in.nextInt(); + int m = in.nextInt(); + int[][] grid = new int[n][m]; + for(int i = 0; i < n; i++){ + for(int j = 0; j < m; j++){ + grid[i][j] = in.nextInt(); + } + } + + int result = 0; + boolean[][] visited = new boolean[n][m]; + for(int i = 0; i < n; i++){ + for(int j = 0; j < m; j++){ + if(!visited[i][j] && grid[i][j] == 1){ + visited[i][j] = true; + count = 1; + dfs(visited, i, j, grid); + //dfs遍历完了一座岛屿,就比较count和result,保留最大的 + result = Math.max(result, count); + } + } + } + System.out.println(result); + } +} +``` +BFS +```java +import java.util.*; +public class Main{ + static int[][] dir = {{0,-1}, {1,0}, {0,1}, {-1, 0}};//下右上左的顺序 + static int count = 0; + public static void bfs(boolean[][] visited, int x, int y, int[][] grid){ + Queue queue = new LinkedList(); + queue.add(new pair(x,y)); + count = 1; //该岛屿的第一块陆地被visit了 + + //对这个岛屿的所有都入队,除非上下左右都没有未访问的陆地 + while(!queue.isEmpty()){ + int curX = queue.peek().x; + int curY = queue.poll().y; + //对每块陆地都进行上下左右的入队和计算(遍历),自然就是按广度优先了 + for(int i = 0; i < 4; i++){ + int nextX = curX + dir[i][0]; + int nextY = curY + dir[i][1]; + if(nextX < 0 || nextY < 0 || nextX >= grid.length || nextY >= grid[0].length){ + continue; + } + if(!visited[nextX][nextY] && grid[nextX][nextY] == 1){ + count++; + queue.add(new pair(nextX, nextY)); + visited[nextX][nextY] = true; + } + } + } + } + + static class pair{ + int x; + int y; + pair(int x, int y){ + this.x = x; + this.y = y; + } + } + + public static void main(String[] args){ + Scanner in = new Scanner(System.in); + int n = in.nextInt(); + int m = in.nextInt(); + int[][] grid = new int[n][m]; + for(int i = 0; i < n; i++){ + for(int j = 0; j < m; j++){ + grid[i][j] = in.nextInt(); + } + } + int result = 0; + boolean[][] visited = new boolean[n][m]; + for(int i = 0; i < n; i++){ + for(int j = 0; j < m; j++){ + if(!visited[i][j] && grid[i][j] == 1){ + visited[i][j] = true; + bfs(visited, i, j, grid); + result = Math.max(result, count); + } + } + } + System.out.println(result); + } +} +``` ### Python DFS From d33c76e74aa90b8ba319af04b0c7f731f6bfabca Mon Sep 17 00:00:00 2001 From: 01geek Date: Wed, 9 Oct 2024 16:28:31 +0800 Subject: [PATCH 22/24] =?UTF-8?q?=E7=BA=A0=E6=AD=A3=20problems/1047.?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E5=AD=97=E7=AC=A6=E4=B8=B2=E4=B8=AD=E7=9A=84?= =?UTF-8?q?=E6=89=80=E6=9C=89=E7=9B=B8=E9=82=BB=E9=87=8D=E5=A4=8D=E9=A1=B9?= =?UTF-8?q?.md=20=E4=B8=ADjava=E7=89=88=E6=9C=AC=E7=9B=B8=E5=85=B3?= =?UTF-8?q?=E6=B3=A8=E9=87=8A=EF=BC=9A=E5=B0=86top>0=E7=BA=A0=E6=AD=A3?= =?UTF-8?q?=E4=B8=BAtop>=3D0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/1047.删除字符串中的所有相邻重复项.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/problems/1047.删除字符串中的所有相邻重复项.md b/problems/1047.删除字符串中的所有相邻重复项.md index 7232008a..51ec4e62 100644 --- a/problems/1047.删除字符串中的所有相邻重复项.md +++ b/problems/1047.删除字符串中的所有相邻重复项.md @@ -164,7 +164,7 @@ class Solution { int top = -1; for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); - // 当 top > 0,即栈中有字符时,当前字符如果和栈中字符相等,弹出栈顶字符,同时 top-- + // 当 top >= 0,即栈中有字符时,当前字符如果和栈中字符相等,弹出栈顶字符,同时 top-- if (top >= 0 && res.charAt(top) == c) { res.deleteCharAt(top); top--; From ba2062471b0a041b748bb543d58514ceb849b21f Mon Sep 17 00:00:00 2001 From: programmercarl <826123027@qq.com> Date: Wed, 9 Oct 2024 16:58:09 +0800 Subject: [PATCH 23/24] Update --- problems/0459.重复的子字符串.md | 22 ++++++++++---------- problems/0518.零钱兑换II.md | 28 ++++++++++++++++++++++---- 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/problems/0459.重复的子字符串.md b/problems/0459.重复的子字符串.md index 254d921d..bee1c102 100644 --- a/problems/0459.重复的子字符串.md +++ b/problems/0459.重复的子字符串.md @@ -64,7 +64,7 @@ 如果有一个字符串s,在 s + s 拼接后, 不算首尾字符,如果能凑成s字符串,说明s 一定是重复子串组成。 -如图,字符串s,图中数字为数组下标,在 s + s 拼接后, 不算首尾字符,中间凑成s字符串。 +如图,字符串s,图中数字为数组下标,在 s + s 拼接后, 不算首尾字符,中间凑成s字符串。 (图中数字为数组下标) ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20240910115555.png) @@ -163,9 +163,7 @@ KMP算法中next数组为什么遇到字符不匹配的时候可以找到上一 如果一个字符串s是由重复子串组成,那么 最长相等前后缀不包含的子串一定是字符串s的最小重复子串。 -证明: 如果s 是有是有最小重复子串p组成。 - -即 s = n * p +如果s 是由最小重复子串p组成,即 s = n * p 那么相同前后缀可以是这样: @@ -203,12 +201,14 @@ p2 = p1,p3 = p2 即: p1 = p2 = p3 最长相等前后缀不包含的子串已经是字符串s的最小重复子串,那么字符串s一定由重复子串组成,这个不需要证明了。 -关键是要要证明:最长相等前后缀不包含的子串什么时候才是字符串s的最小重复子串呢。 +关键是要证明:最长相等前后缀不包含的子串什么时候才是字符串s的最小重复子串呢。 -情况一, 最长相等前后缀不包含的子串的长度 比 字符串s的一半的长度还大,那一定不是字符串s的重复子串 +情况一, 最长相等前后缀不包含的子串的长度 比 字符串s的一半的长度还大,那一定不是字符串s的重复子串,如图: ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20240911110236.png) +图中:前后缀不包含的子串的长度 大于 字符串s的长度的 二分之一 + -------------- 情况二,最长相等前后缀不包含的子串的长度 可以被 字符串s的长度整除,如图: @@ -230,7 +230,7 @@ p2 = p1,p3 = p2 即: p1 = p2 = p3 即 s[0]s[1] 是最小重复子串 -以上推导中,录友可能想,你怎么知道 s[0] 和 s[1] 就不相同呢? s[0] 为什么就不能使最小重复子串。 +以上推导中,录友可能想,你怎么知道 s[0] 和 s[1] 就不相同呢? s[0] 为什么就不能是最小重复子串。 如果 s[0] 和 s[1] 也相同,同时 s[0]s[1]与s[2]s[3]相同,s[2]s[3] 与 s[4]s[5]相同,s[4]s[5] 与 s[6]s[7] 相同,那么这个字符串就是有一个字符构成的字符串。 @@ -246,7 +246,7 @@ p2 = p1,p3 = p2 即: p1 = p2 = p3 或者说,自己举个例子,`aaaaaa`,这个字符串,他的最长相等前后缀是什么? -同上以上推导,最长相等前后缀不包含的子串的长度只要被 字符串s的长度整除,就是一定是最小重复子串。 +同上以上推导,最长相等前后缀不包含的子串的长度只要被 字符串s的长度整除,最长相等前后缀不包含的子串一定是最小重复子串。 ---------------- @@ -267,7 +267,7 @@ p2 = p1,p3 = p2 即: p1 = p2 = p3 以上推导,可以得出 s[0],s[1],s[2] 与 s[3],s[4],s[5] 相同,s[3]s[4] 与 s[6]s[7]相同。 -那么 最长相等前后缀不包含的子串的长度 不被 字符串s的长度整除 ,就不是s的重复子串 +那么 最长相等前后缀不包含的子串的长度 不被 字符串s的长度整除 ,最长相等前后缀不包含的子串就不是s的重复子串 ----------- @@ -277,7 +277,7 @@ p2 = p1,p3 = p2 即: p1 = p2 = p3 在必要条件,这个是 显而易见的,都已经假设 最长相等前后缀不包含的子串 是 s的最小重复子串了,那s必然是重复子串。 -关键是需要证明, 字符串s的最长相等前后缀不包含的子串 什么时候才是 s最小重复子串。 +**关键是需要证明, 字符串s的最长相等前后缀不包含的子串 什么时候才是 s最小重复子串**。 同上我们证明了,当 最长相等前后缀不包含的子串的长度 可以被 字符串s的长度整除,那么不包含的子串 就是s的最小重复子串。 @@ -312,7 +312,7 @@ next 数组记录的就是最长相同前后缀( [字符串:KMP算法精讲] 4可以被 12(字符串的长度) 整除,所以说明有重复的子字符串(asdf)。 -### 打码实现 +### 代码实现 C++代码如下:(这里使用了前缀表统一减一的实现方式) diff --git a/problems/0518.零钱兑换II.md b/problems/0518.零钱兑换II.md index 255912d6..360da582 100644 --- a/problems/0518.零钱兑换II.md +++ b/problems/0518.零钱兑换II.md @@ -168,23 +168,43 @@ for (int j = 0; j <= amount; j++) { // 遍历背包容量 class Solution { public: int change(int amount, vector& coins) { - vector dp(amount + 1, 0); - dp[0] = 1; + vector dp(amount + 1, 0); // 防止相加数据超int + dp[0] = 1; // 只有一种方式达到0 for (int i = 0; i < coins.size(); i++) { // 遍历物品 for (int j = coins[i]; j <= amount; j++) { // 遍历背包 dp[j] += dp[j - coins[i]]; } } - return dp[amount]; + return dp[amount]; // 返回组合数 } }; ``` +C++测试用例有两个数相加超过int的数据,所以需要在if里加上dp[i] < INT_MAX - dp[i - num]。 + * 时间复杂度: O(mn),其中 m 是amount,n 是 coins 的长度 * 空间复杂度: O(m) +为了防止相加的数据 超int 也可以这么写: + +```CPP +class Solution { +public: + int change(int amount, vector& coins) { + vector dp(amount + 1, 0); + dp[0] = 1; // 只有一种方式达到0 + for (int i = 0; i < coins.size(); i++) { // 遍历物品 + for (int j = coins[i]; j <= amount; j++) { // 遍历背包 + if (dp[j] < INT_MAX - dp[j - coins[i]]) { //防止相加数据超int + dp[j] += dp[j - coins[i]]; + } + } + } + return dp[amount]; // 返回组合数 + } +}; +``` -是不是发现代码如此精简 ## 总结 From 8f692f8ff4545337e9df4790fa2cdb7f9a07c219 Mon Sep 17 00:00:00 2001 From: 01geek Date: Wed, 9 Oct 2024 17:36:56 +0800 Subject: [PATCH 24/24] =?UTF-8?q?=E7=BA=A0=E6=AD=A3=200150.=E9=80=86?= =?UTF-8?q?=E6=B3=A2=E5=85=B0=E8=A1=A8=E8=BE=BE=E5=BC=8F=E6=B1=82=E5=80=BC?= =?UTF-8?q?.md=20=E7=9A=84c++=E4=BB=A3=E7=A0=81=EF=BC=8C=E5=B0=86=E7=AC=AC?= =?UTF-8?q?21=E8=A1=8C=E4=BB=A3=E7=A0=81=E7=9A=84int=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E4=B8=BAlong=20long=EF=BC=8C=E5=8E=9F=E5=9B=A0=EF=BC=9A?= =?UTF-8?q?=E6=97=A2=E7=84=B6=E5=89=8D=E9=9D=A2=E8=80=83=E8=99=91=E5=88=B0?= =?UTF-8?q?=E5=8F=AF=E8=83=BD=E6=95=B0=E6=8D=AE=E5=80=BC=E5=A4=A7=E8=80=8C?= =?UTF-8?q?=E5=B0=86int=E6=94=B9=E4=B8=BA=E4=BA=86long=20long=EF=BC=8C?= =?UTF-8?q?=E9=82=A3=E4=B9=88=E6=9C=80=E5=90=8E=E7=9A=84RPN=E8=BF=90?= =?UTF-8?q?=E7=AE=97=E7=BB=93=E6=9E=9C=E4=B9=9F=E5=8F=AF=E8=83=BD=E8=B6=85?= =?UTF-8?q?=E8=BF=87int=E8=83=BD=E8=A1=A8=E7=A4=BA=E7=9A=84=E8=8C=83?= =?UTF-8?q?=E5=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0150.逆波兰表达式求值.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/problems/0150.逆波兰表达式求值.md b/problems/0150.逆波兰表达式求值.md index 48e99c5b..7d4031d7 100644 --- a/problems/0150.逆波兰表达式求值.md +++ b/problems/0150.逆波兰表达式求值.md @@ -108,7 +108,7 @@ public: } } - int result = st.top(); + long long result = st.top(); st.pop(); // 把栈里最后一个元素弹出(其实不弹出也没事) return result; }