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 01/65] =?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 02/65] =?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 03/65] =?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 5fb0a12fa14d826ee37179f6807d3e332ae46d76 Mon Sep 17 00:00:00 2001 From: suinming <0223314338aa@gmail.com> Date: Tue, 1 Oct 2024 17:39:24 +0800 Subject: [PATCH 04/65] =?UTF-8?q?feat:=20127.=20=E9=AA=91=E5=A3=AB?= =?UTF-8?q?=E7=9A=84=E6=94=BB=E5=87=BB=E5=A2=9E=E5=8A=A0js=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/0126.骑士的攻击astar.md | 125 ++++++++++++++++++ 1 file changed, 125 insertions(+) diff --git a/problems/kamacoder/0126.骑士的攻击astar.md b/problems/kamacoder/0126.骑士的攻击astar.md index 2d0481ec..1cdba07d 100644 --- a/problems/kamacoder/0126.骑士的攻击astar.md +++ b/problems/kamacoder/0126.骑士的攻击astar.md @@ -375,6 +375,131 @@ for _ in range(n): ### Javascript +```js +class MinHeap { + constructor() { + this.val = [] + } + push(val) { + this.val.push(val) + if (this.val.length > 1) { + this.bubbleUp() + } + } + bubbleUp() { + let pi = this.val.length - 1 + let pp = Math.floor((pi - 1) / 2) + while (pi > 0 && this.val[pp][0] > this.val[pi][0]) { + ;[this.val[pi], this.val[pp]] = [this.val[pp], this.val[pi]] + pi = pp + pp = Math.floor((pi - 1) / 2) + } + } + pop() { + if (this.val.length > 1) { + let pp = 0 + let pi = this.val.length - 1 + ;[this.val[pi], this.val[pp]] = [this.val[pp], this.val[pi]] + const min = this.val.pop() + if (this.val.length > 1) { + this.sinkDown(0) + } + return min + } else if (this.val.length == 1) { + return this.val.pop() + } + + } + sinkDown(parentIdx) { + let pp = parentIdx + let plc = pp * 2 + 1 + let prc = pp * 2 + 2 + let pt = pp // temp pointer + if (plc < this.val.length && this.val[pp][0] > this.val[plc][0]) { + pt = plc + } + if (prc < this.val.length && this.val[pt][0] > this.val[prc][0]) { + pt = prc + } + if (pt != pp) { + ;[this.val[pp], this.val[pt]] = [this.val[pt], this.val[pp]] + this.sinkDown(pt) + } + } +} + +const moves = [ + [1, 2], + [2, 1], + [-1, -2], + [-2, -1], + [-1, 2], + [-2, 1], + [1, -2], + [2, -1] +] + +function dist(a, b) { + return ((a[0] - b[0])**2 + (a[1] - b[1])**2)**0.5 +} + +function isValid(x, y) { + return x >= 1 && y >= 1 && x < 1001 && y < 1001 +} + +function bfs(start, end) { + const step = new Map() + step.set(start.join(" "), 0) + const q = new MinHeap() + q.push([dist(start, end), start[0], start[1]]) + + while(q.val.length) { + const [d, x, y] = q.pop() + // if x and y correspond to end position output result + if (x == end[0] && y == end[1]) { + console.log(step.get(end.join(" "))) + break; + } + for (const [dx, dy] of moves) { + const nx = dx + x + const ny = dy + y + if (isValid(nx, ny)) { + const newStep = step.get([x, y].join(" ")) + 1 + const newDist = dist([nx, ny], [...end]) + const s = step.get([nx, ny].join(" ")) ? + step.get([nx, ny]) : + Number.MAX_VALUE + if (newStep < s) { + q.push( + [ + newStep + newDist, + nx, + ny + ] + ) + step.set([nx, ny].join(" "), newStep) + } + } + } + } +} + +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 = Number((await readline())) + + // find min step + for (let i = 0 ; i < n ; i++) { + const [s1, s2, t1, t2] = (await readline()).split(" ").map(Number) + bfs([s1, s2], [t1, t2]) + } +} + +main() +``` + ### TypeScript ### PhP From 07d219ecd1fb75337d6d5722a1b63635e4f19057 Mon Sep 17 00:00:00 2001 From: Yufan Sheng <18829237653@163.com> Date: Fri, 4 Oct 2024 21:05:14 +1000 Subject: [PATCH 05/65] =?UTF-8?q?=E6=9B=B4=E6=AD=A3=E5=A4=8D=E6=9D=82?= =?UTF-8?q?=E5=BA=A6=E5=88=86=E6=9E=90=E4=B8=AD=E7=9A=84=E7=AC=94=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0452.用最少数量的箭引爆气球.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/problems/0452.用最少数量的箭引爆气球.md b/problems/0452.用最少数量的箭引爆气球.md index 318c3035..10fe5771 100644 --- a/problems/0452.用最少数量的箭引爆气球.md +++ b/problems/0452.用最少数量的箭引爆气球.md @@ -110,7 +110,7 @@ public: ``` * 时间复杂度:O(nlog n),因为有一个快排 -* 空间复杂度:O(1),有一个快排,最差情况(倒序)时,需要n次递归调用。因此确实需要O(n)的栈空间 +* 空间复杂度:O(n),有一个快排,最差情况(倒序)时,需要n次递归调用。因此确实需要O(n)的栈空间 可以看出代码并不复杂。 From 2b7fc7d1e183ebcce3930b0235f7f646a6ab3871 Mon Sep 17 00:00:00 2001 From: Yufan Sheng <18829237653@163.com> Date: Fri, 4 Oct 2024 21:22:50 +1000 Subject: [PATCH 06/65] =?UTF-8?q?=E5=88=A0=E9=99=A4=E5=86=97=E4=BD=99?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=EF=BC=8C=E5=A2=9E=E5=8A=A0=E8=AF=A6=E7=BB=86?= =?UTF-8?q?=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../0452.用最少数量的箭引爆气球.md | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/problems/0452.用最少数量的箭引爆气球.md b/problems/0452.用最少数量的箭引爆气球.md index 10fe5771..2099275d 100644 --- a/problems/0452.用最少数量的箭引爆气球.md +++ b/problems/0452.用最少数量的箭引爆气球.md @@ -180,19 +180,25 @@ class Solution: ```python class Solution: # 不改变原数组 def findMinArrowShots(self, points: List[List[int]]) -> int: + if len(points) == 0: + return 0 + points.sort(key = lambda x: x[0]) - sl,sr = points[0][0],points[0][1] + + # points已经按照第一个坐标正序排列,因此只需要设置一个变量,记录右侧坐标(阈值) + # 考虑一个气球范围包含两个不相交气球的情况:气球1: [1, 10], 气球2: [2, 5], 气球3: [6, 10] + curr_min_right = points[0][1] count = 1 + for i in points: - if i[0]>sr: - count+=1 - sl,sr = i[0],i[1] + if i[0] > curr_min_right: + # 当气球左侧大于这个阈值,那么一定就需要在发射一只箭,并且将阈值更新为当前气球的右侧 + count += 1 + curr_min_right = i[1] else: - sl = max(sl,i[0]) - sr = min(sr,i[1]) + # 否则的话,我们只需要求阈值和当前气球的右侧的较小值来更新阈值 + curr_min_right = min(curr_min_right, i[1]) return count - - ``` ### Go ```go From 91137dc297f7a9ca7abb2d59fd9c45afe04f2366 Mon Sep 17 00:00:00 2001 From: Jasonyou <2926593225@qq.com> Date: Thu, 3 Oct 2024 19:39:17 +0800 Subject: [PATCH 07/65] =?UTF-8?q?fix:=20Errata=20=E8=BE=93=E5=87=BA?= =?UTF-8?q?=E8=BE=93=E5=87=BA->=E8=BE=93=E5=85=A5=E8=BE=93=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/kamacoder/0098.所有可达路径.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/problems/kamacoder/0098.所有可达路径.md b/problems/kamacoder/0098.所有可达路径.md index db35524f..a2f60a90 100644 --- a/problems/kamacoder/0098.所有可达路径.md +++ b/problems/kamacoder/0098.所有可达路径.md @@ -277,7 +277,7 @@ ACM格式大家在输出结果的时候,要关注看看格式问题,特别 有录友可能会想,ACM格式就是麻烦,有空格没有空格有什么影响,结果对了不就行了? -ACM模式相对于核心代码模式(力扣) 更考验大家对代码的掌控能力。 例如工程代码里,输出输出都是要自己控制的。这也是为什么大公司笔试,都是ACM模式。 +ACM模式相对于核心代码模式(力扣) 更考验大家对代码的掌控能力。 例如工程代码里,输入输出都是要自己控制的。这也是为什么大公司笔试,都是ACM模式。 以上代码中,结果都存在了 result数组里(二维数组,每一行是一个结果),最后将其打印出来。(重点看注释) From 4eef0863a293b7f2cfd36214a3281ae26093022e Mon Sep 17 00:00:00 2001 From: Jasonyou <2926593225@qq.com> Date: Fri, 4 Oct 2024 21:18:01 +0800 Subject: [PATCH 08/65] =?UTF-8?q?feat:=200100.=E5=B2=9B=E5=B1=BF=E6=9C=80?= =?UTF-8?q?=E5=A4=A7=E9=9D=A2=E7=A7=AF=20Java=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kamacoder/0100.岛屿的最大面积.md | 123 +++++++++++++++++- 1 file changed, 122 insertions(+), 1 deletion(-) diff --git a/problems/kamacoder/0100.岛屿的最大面积.md b/problems/kamacoder/0100.岛屿的最大面积.md index 51bfc57f..871925df 100644 --- a/problems/kamacoder/0100.岛屿的最大面积.md +++ b/problems/kamacoder/0100.岛屿的最大面积.md @@ -222,7 +222,128 @@ public: ## 其他语言版本 -### Java +### Java + +```java +import java.util.*; +import java.math.*; + +/** + * DFS版 + */ +public class Main{ + + static final int[][] dir={{0,1},{1,0},{0,-1},{-1,0}}; + static int result=0; + static int count=0; + + public static void main(String[] args){ + Scanner scanner = new Scanner(System.in); + int n = scanner.nextInt(); + int m = scanner.nextInt(); + int[][] map = new int[n][m]; + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + map[i][j]=scanner.nextInt(); + } + } + boolean[][] visited = new boolean[n][m]; + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + if(!visited[i][j]&&map[i][j]==1){ + count=0; + dfs(map,visited,i,j); + result= Math.max(count, result); + } + } + } + System.out.println(result); + } + + static void dfs(int[][] map,boolean[][] visited,int x,int y){ + count++; + visited[x][y]=true; + for (int i = 0; i < 4; i++) { + int nextX=x+dir[i][0]; + int nextY=y+dir[i][1]; + //水或者已经访问过的跳过 + if(nextX<0||nextY<0 + ||nextX>=map.length||nextY>=map[0].length + ||visited[nextX][nextY]||map[nextX][nextY]==0)continue; + + dfs(map,visited,nextX,nextY); + } + } +} +``` + +```java +import java.util.*; +import java.math.*; + +/** + * BFS版 + */ +public class Main { + static class Node { + int x; + int y; + + public Node(int x, int y) { + this.x = x; + this.y = y; + } + } + + static final int[][] dir = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; + static int result = 0; + static int count = 0; + + public static void main(String[] args) { + Scanner scanner = new Scanner(System.in); + int n = scanner.nextInt(); + int m = scanner.nextInt(); + int[][] map = new int[n][m]; + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + map[i][j] = scanner.nextInt(); + } + } + boolean[][] visited = new boolean[n][m]; + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + if (!visited[i][j] && map[i][j] == 1) { + count = 0; + bfs(map, visited, i, j); + result = Math.max(count, result); + } + } + } + System.out.println(result); + } + + static void bfs(int[][] map, boolean[][] visited, int x, int y) { + Queue q = new LinkedList<>(); + q.add(new Node(x, y)); + visited[x][y] = true; + count++; + while (!q.isEmpty()) { + Node node = q.remove(); + for (int i = 0; i < 4; i++) { + int nextX = node.x + dir[i][0]; + int nextY = node.y + dir[i][1]; + if (nextX < 0 || nextY < 0 || nextX >= map.length || nextY >= map[0].length || visited[nextX][nextY] || map[nextX][nextY] == 0) + continue; + q.add(new Node(nextX, nextY)); + visited[nextX][nextY] = true; + count++; + } + } + } +} + +``` + ### Python From 9c7131e253ad9b59aaa69f102f03e0154752b660 Mon Sep 17 00:00:00 2001 From: Jasonyou <2926593225@qq.com> Date: Sun, 6 Oct 2024 03:04:09 +0800 Subject: [PATCH 09/65] =?UTF-8?q?feate:=20=E5=AD=97=E7=AC=A6=E4=B8=B2?= =?UTF-8?q?=E6=8E=A5=E9=BE=99=20=20Java=E4=BC=98=E5=8C=96=E7=89=88?= =?UTF-8?q?=E5=B9=B6=E4=BF=AE=E5=A4=8D=E5=AD=98=E5=9C=A8=E9=97=AE=E9=A2=98?= =?UTF-8?q?=201.=E4=BD=BF=E7=94=A8null=E6=A0=87=E5=BF=97=E5=88=86=E5=B1=82?= =?UTF-8?q?=202.=E5=AF=BB=E6=89=BE=E9=82=BB=E6=8E=A5=E8=8A=82=E7=82=B9?= =?UTF-8?q?=E6=97=B6=EF=BC=8C=E5=9B=9E=E6=BB=9A=E4=BF=AE=E6=94=B9=EF=BC=8C?= =?UTF-8?q?=E9=81=BF=E5=85=8D=E5=A4=9A=E6=AC=A1=E6=95=B0=E7=BB=84=E5=A4=8D?= =?UTF-8?q?=E5=88=B6=203.=E4=BF=AE=E5=A4=8D=E8=BE=B9=E7=95=8C=E6=9D=A1?= =?UTF-8?q?=E4=BB=B6=EF=BC=9AbeginStr=3D=3DendStr=E6=97=B6=EF=BC=8C?= =?UTF-8?q?=E5=BA=94=E8=AF=A5=E8=BE=93=E5=87=BA0=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/kamacoder/0110.字符串接龙.md | 106 +++++++++++---------- 1 file changed, 55 insertions(+), 51 deletions(-) diff --git a/problems/kamacoder/0110.字符串接龙.md b/problems/kamacoder/0110.字符串接龙.md index 308e50b7..ef261c4d 100644 --- a/problems/kamacoder/0110.字符串接龙.md +++ b/problems/kamacoder/0110.字符串接龙.md @@ -152,66 +152,70 @@ int main() { ## 其他语言版本 -### Java +### Java + ```Java +import java.util.*; + public class Main { - // BFS方法 - public static int ladderLength(String beginWord, String endWord, List wordList) { - // 使用set作为查询容器,效率更高 - HashSet set = new HashSet<>(wordList); - - // 声明一个queue存储每次变更一个字符得到的且存在于容器中的新字符串 - Queue queue = new LinkedList<>(); - - // 声明一个hashMap存储遍历到的字符串以及所走过的路径path - HashMap visitMap = new HashMap<>(); - queue.offer(beginWord); - visitMap.put(beginWord, 1); - - while (!queue.isEmpty()) { - String curWord = queue.poll(); - int path = visitMap.get(curWord); + public static void main(String[] args) { + Scanner scanner = new Scanner(System.in); + int n = scanner.nextInt(); + scanner.nextLine(); + String beginStr = scanner.next(); + String endStr = scanner.next(); + scanner.nextLine(); + List wordList = new ArrayList<>(); + wordList.add(beginStr); + wordList.add(endStr); + for (int i = 0; i < n; i++) { + wordList.add(scanner.nextLine()); + } + int count = bfs(beginStr, endStr, wordList); + System.out.println(count); + } - for (int i = 0; i < curWord.length(); i++) { - char[] ch = curWord.toCharArray(); - // 每个位置尝试26个字母 - for (char k = 'a'; k <= 'z'; k++) { - ch[i] = k; - - String newWord = new String(ch); - if (newWord.equals(endWord)) return path + 1; - - // 如果这个新字符串存在于容器且之前未被访问到 - if (set.contains(newWord) && !visitMap.containsKey(newWord)) { - visitMap.put(newWord, path + 1); - queue.offer(newWord); + /** + * 广度优先搜索-寻找最短路径 + */ + public static int bfs(String beginStr, String endStr, List wordList) { + int len = 1; + Set set = new HashSet<>(wordList); + Set visited = new HashSet<>(); + Queue q = new LinkedList<>(); + visited.add(beginStr); + q.add(beginStr); + q.add(null); + while (!q.isEmpty()) { + String node = q.remove(); + //上一层结束,若下一层还有节点进入下一层 + if (node == null) { + if (!q.isEmpty()) { + len++; + q.add(null); + } + continue; + } + char[] charArray = node.toCharArray(); + //寻找邻接节点 + for (int i = 0; i < charArray.length; i++) { + //记录旧值,用于回滚修改 + char old = charArray[i]; + for (char j = 'a'; j <= 'z'; j++) { + charArray[i] = j; + String newWord = new String(charArray); + if (set.contains(newWord) && !visited.contains(newWord)) { + q.add(newWord); + visited.add(newWord); + //找到结尾 + if (newWord.equals(endStr)) return len + 1; } } + charArray[i] = old; } } - return 0; } - - public static void main (String[] args) { - /* code */ - // 接收输入 - Scanner sc = new Scanner(System.in); - int N = sc.nextInt(); - sc.nextLine(); - String[] strs = sc.nextLine().split(" "); - - List wordList = new ArrayList<>(); - for (int i = 0; i < N; i++) { - wordList.add(sc.nextLine()); - } - - // wordList.add(strs[1]); - - // 打印结果 - int result = ladderLength(strs[0], strs[1], wordList); - System.out.println(result); - } } ``` From d3804674e4b26d29800720a35d42c177a5a49e66 Mon Sep 17 00:00:00 2001 From: Jasonyou <2926593225@qq.com> Date: Mon, 7 Oct 2024 06:29:20 +0800 Subject: [PATCH 10/65] =?UTF-8?q?perf=EF=BC=9A=E5=B0=81=E8=A3=85=E6=88=90?= =?UTF-8?q?=E7=B1=BB=EF=BC=8C=E7=90=86=E8=A7=A3=E8=B5=B7=E6=9D=A5=E6=9B=B4?= =?UTF-8?q?=E5=AE=B9=E6=98=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/kamacoder/0109.冗余连接II.md | 182 ++++++++++++---------- 1 file changed, 104 insertions(+), 78 deletions(-) diff --git a/problems/kamacoder/0109.冗余连接II.md b/problems/kamacoder/0109.冗余连接II.md index 2bd4eac6..56959d87 100644 --- a/problems/kamacoder/0109.冗余连接II.md +++ b/problems/kamacoder/0109.冗余连接II.md @@ -250,105 +250,131 @@ int main() { ## 其他语言版本 ### Java + ```java -import java.util.ArrayList; -import java.util.List; -import java.util.Scanner; +import java.util.*; +/* + * 冗余连接II。主要问题是存在入度为2或者成环,也可能两个问题同时存在。 + * 1.判断入度为2的边 + * 2.判断是否成环(并查集) + */ + public class Main { - static int n; - static int[] father = new int[1001]; // 并查集数组 + /** + * 并查集模板 + */ + static class Disjoint { - // 并查集初始化 - public static void init() { - for (int i = 1; i <= n; ++i) { - father[i] = i; - } - } + private final int[] father; - // 并查集里寻根的过程 - public static int find(int u) { - if (u == father[u]) return u; - return father[u] = find(father[u]); // 路径压缩 - } - - // 将 v->u 这条边加入并查集 - public static void join(int u, int v) { - u = find(u); - v = find(v); - if (u != v) { - father[v] = u; // 合并两棵树 - } - } - - // 判断 u 和 v 是否有同一个根 - public static boolean same(int u, int v) { - return find(u) == find(v); - } - - // 在有向图里找到删除的那条边,使其变成树 - public static void getRemoveEdge(List edges) { - init(); // 初始化并查集 - for (int i = 0; i < n; i++) { // 遍历所有的边 - if (same(edges.get(i)[0], edges.get(i)[1])) { // 如果构成有向环了,就是要删除的边 - System.out.println(edges.get(i)[0] + " " + edges.get(i)[1]); - return; - } else { - join(edges.get(i)[0], edges.get(i)[1]); + public Disjoint(int n) { + father = new int[n]; + for (int i = 0; i < n; i++) { + father[i] = i; } } + + public void join(int n, int m) { + n = find(n); + m = find(m); + if (n == m) return; + father[n] = m; + } + + public int find(int n) { + return father[n] == n ? n : (father[n] = find(father[n])); + } + + public boolean isSame(int n, int m) { + return find(n) == find(m); + } } - // 删一条边之后判断是不是树 - public static boolean isTreeAfterRemoveEdge(List edges, int deleteEdge) { - init(); // 初始化并查集 + static class Edge { + int s; + int t; + + public Edge(int s, int t) { + this.s = s; + this.t = t; + } + } + + static class Node { + int id; + int in; + int out; + } + + public static void main(String[] args) { + Scanner scanner = new Scanner(System.in); + int n = scanner.nextInt(); + List edges = new ArrayList<>(); + Node[] nodeMap = new Node[n + 1]; + for (int i = 1; i <= n; i++) { + nodeMap[i] = new Node(); + } + Integer doubleIn = null; for (int i = 0; i < n; i++) { - if (i == deleteEdge) continue; - if (same(edges.get(i)[0], edges.get(i)[1])) { // 如果构成有向环了,一定不是树 + int s = scanner.nextInt(); + int t = scanner.nextInt(); + //记录入度 + nodeMap[t].in++; + if (!(nodeMap[t].in < 2)) doubleIn = t; + Edge edge = new Edge(s, t); + edges.add(edge); + } + Edge result = null; + //存在入度为2的节点,既要消除入度为2的问题同时解除可能存在的环 + if (doubleIn != null) { + List doubleInEdges = new ArrayList<>(); + for (Edge edge : edges) { + if (edge.t == doubleIn) doubleInEdges.add(edge); + if (doubleInEdges.size() == 2) break; + } + Edge edge = doubleInEdges.get(1); + if (isTreeWithExclude(edges, edge, nodeMap)) { + result = edge; + } else { + result = doubleInEdges.get(0); + } + } else { + //不存在入度为2的节点,则只需要解除环即可 + result = getRemoveEdge(edges, nodeMap); + } + + System.out.println(result.s + " " + result.t); + } + + public static boolean isTreeWithExclude(List edges, Edge exculdEdge, Node[] nodeMap) { + Disjoint disjoint = new Disjoint(nodeMap.length + 1); + for (Edge edge : edges) { + if (edge == exculdEdge) continue; + //成环则不是树 + if (disjoint.isSame(edge.s, edge.t)) { return false; } - join(edges.get(i)[0], edges.get(i)[1]); + disjoint.join(edge.s, edge.t); } return true; } - public static void main(String[] args) { - Scanner sc = new Scanner(System.in); - List edges = new ArrayList<>(); // 存储所有的边 + public static Edge getRemoveEdge(List edges, Node[] nodeMap) { + int length = nodeMap.length; + Disjoint disjoint = new Disjoint(length); - n = sc.nextInt(); // 顶点数 - int[] inDegree = new int[n + 1]; // 记录每个节点的入度 - for (int i = 0; i < n; i++) { - int s = sc.nextInt(); // 边的起点 - int t = sc.nextInt(); // 边的终点 - inDegree[t]++; - edges.add(new int[]{s, t}); // 将边加入列表 + for (Edge edge : edges) { + if (disjoint.isSame(edge.s, edge.t)) return edge; + disjoint.join(edge.s, edge.t); } - - List vec = new ArrayList<>(); // 记录入度为2的边(如果有的话就两条边) - // 找入度为2的节点所对应的边,注意要倒序,因为优先删除最后出现的一条边 - for (int i = n - 1; i >= 0; i--) { - if (inDegree[edges.get(i)[1]] == 2) { - vec.add(i); - } - } - - // 情况一、情况二 - if (vec.size() > 0) { - // vec里的边已经按照倒叙放的,所以优先删 vec.get(0) 这条边 - if (isTreeAfterRemoveEdge(edges, vec.get(0))) { - System.out.println(edges.get(vec.get(0))[0] + " " + edges.get(vec.get(0))[1]); - } else { - System.out.println(edges.get(vec.get(1))[0] + " " + edges.get(vec.get(1))[1]); - } - return; - } - - // 处理情况三:明确没有入度为2的情况,一定有有向环,找到构成环的边返回即可 - getRemoveEdge(edges); + return null; } + } + ``` + ### Python ```python From 8669f2ad20f3c7f550557584fa57b4622e5862e7 Mon Sep 17 00:00:00 2001 From: Leehouc <152672308+Leehouc@users.noreply.github.com> Date: Mon, 7 Oct 2024 13:19:27 +0800 Subject: [PATCH 11/65] =?UTF-8?q?=E4=BF=AE=E6=94=B90459.=E9=87=8D=E5=A4=8D?= =?UTF-8?q?=E7=9A=84=E5=AD=90=E5=AD=97=E7=AC=A6=E4=B8=B2.md=E9=94=99?= =?UTF-8?q?=E5=88=AB=E5=AD=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 打码->代码 --- problems/0459.重复的子字符串.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/problems/0459.重复的子字符串.md b/problems/0459.重复的子字符串.md index dbf32e64..5c86e122 100644 --- a/problems/0459.重复的子字符串.md +++ b/problems/0459.重复的子字符串.md @@ -312,7 +312,7 @@ next 数组记录的就是最长相同前后缀( [字符串:KMP算法精讲] 4可以被 12(字符串的长度) 整除,所以说明有重复的子字符串(asdf)。 -### 打码实现 +### 代码实现 C++代码如下:(这里使用了前缀表统一减一的实现方式) From fdae38cf7e575cc01f3db7807ca48b942dcf2cd2 Mon Sep 17 00:00:00 2001 From: markwang Date: Tue, 8 Oct 2024 15:16:23 +0800 Subject: [PATCH 12/65] =?UTF-8?q?337.=E6=89=93=E5=AE=B6=E5=8A=AB=E8=88=8DI?= =?UTF-8?q?II=E5=A2=9E=E5=8A=A0Go=E9=80=92=E5=BD=92=E8=A7=A3=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0337.打家劫舍III.md | 84 ++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/problems/0337.打家劫舍III.md b/problems/0337.打家劫舍III.md index 7aae5cbf..12e31aba 100644 --- a/problems/0337.打家劫舍III.md +++ b/problems/0337.打家劫舍III.md @@ -388,6 +388,90 @@ class Solution: ### Go +暴力递归 + +```go +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +func rob(root *TreeNode) int { + if root == nil { + return 0 + } + if root.Left == nil && root.Right == nil { + return root.Val + } + // 偷父节点 + val1 := root.Val + if root.Left != nil { + val1 += rob(root.Left.Left) + rob(root.Left.Right) // 跳过root->left,相当于不考虑左孩子了 + } + if root.Right != nil { + val1 += rob(root.Right.Left) + rob(root.Right.Right) // 跳过root->right,相当于不考虑右孩子了 + } + // 不偷父节点 + val2 := rob(root.Left) + rob(root.Right) // 考虑root的左右孩子 + return max(val1, val2) +} + +func max(x, y int) int { + if x > y { + return x + } + return y +} +``` + +记忆化递推 + +```go +/** + * Definition for a binary tree node. + * type TreeNode struct { + * Val int + * Left *TreeNode + * Right *TreeNode + * } + */ +var umap = make(map[*TreeNode]int) + +func rob(root *TreeNode) int { + if root == nil { + return 0 + } + if root.Left == nil && root.Right == nil { + return root.Val + } + if val, ok := umap[root]; ok { + return val // 如果umap里已经有记录则直接返回 + } + // 偷父节点 + val1 := root.Val + if root.Left != nil { + val1 += rob(root.Left.Left) + rob(root.Left.Right) // 跳过root->left,相当于不考虑左孩子了 + } + if root.Right != nil { + val1 += rob(root.Right.Left) + rob(root.Right.Right) // 跳过root->right,相当于不考虑右孩子了 + } + // 不偷父节点 + val2 := rob(root.Left) + rob(root.Right) // 考虑root的左右孩子 + umap[root] = max(val1, val2) // umap记录一下结果 + return max(val1, val2) +} + +func max(x, y int) int { + if x > y { + return x + } + return y +} +``` + 动态规划 ```go From d33c76e74aa90b8ba319af04b0c7f731f6bfabca Mon Sep 17 00:00:00 2001 From: 01geek Date: Wed, 9 Oct 2024 16:28:31 +0800 Subject: [PATCH 13/65] =?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 8f692f8ff4545337e9df4790fa2cdb7f9a07c219 Mon Sep 17 00:00:00 2001 From: 01geek Date: Wed, 9 Oct 2024 17:36:56 +0800 Subject: [PATCH 14/65] =?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; } From baf7ed122b1cb78b89565b83b343a4f3c5f5ec82 Mon Sep 17 00:00:00 2001 From: "junjie2.luo" Date: Thu, 10 Oct 2024 17:18:04 +0800 Subject: [PATCH 15/65] =?UTF-8?q?feat:=201207.=E7=8B=AC=E4=B8=80=E6=97=A0?= =?UTF-8?q?=E4=BA=8C=E7=9A=84=E5=87=BA=E7=8E=B0=E6=AC=A1=E6=95=B0,?= =?UTF-8?q?=E6=96=B0=E5=A2=9Erust=E8=A7=A3=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/1207.独一无二的出现次数.md | 22 ++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/problems/1207.独一无二的出现次数.md b/problems/1207.独一无二的出现次数.md index cd89522e..781badf5 100644 --- a/problems/1207.独一无二的出现次数.md +++ b/problems/1207.独一无二的出现次数.md @@ -221,6 +221,28 @@ func uniqueOccurrences(arr []int) bool { } ``` +### Rust + +```rust +use std::collections::{HashMap, HashSet}; +impl Solution { + pub fn unique_occurrences(arr: Vec) -> bool { + let mut hash = HashMap::::new(); + for x in arr { + *hash.entry(x).or_insert(0) += 1; + } + let mut set = HashSet::::new(); + for (_k, v) in hash { + if set.contains(&v) { + return false + } else { + set.insert(v); + } + } + true + } +} +``` From e43323b1e1f3556dc7bc38b4ae6bdd13508e0aea Mon Sep 17 00:00:00 2001 From: "junjie2.luo" Date: Thu, 10 Oct 2024 17:18:41 +0800 Subject: [PATCH 16/65] =?UTF-8?q?feat:=201365.=E6=9C=89=E5=A4=9A=E5=B0=91?= =?UTF-8?q?=E5=B0=8F=E4=BA=8E=E5=BD=93=E5=89=8D=E6=95=B0=E5=AD=97=E7=9A=84?= =?UTF-8?q?=E6=95=B0=E5=AD=97,=E6=96=B0=E5=A2=9Erust=E8=A7=A3=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../1365.有多少小于当前数字的数字.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/problems/1365.有多少小于当前数字的数字.md b/problems/1365.有多少小于当前数字的数字.md index 94c1eb77..64f61096 100644 --- a/problems/1365.有多少小于当前数字的数字.md +++ b/problems/1365.有多少小于当前数字的数字.md @@ -260,6 +260,22 @@ function smallerNumbersThanCurrent(nums: number[]): number[] { }; ``` +### rust +```rust +use std::collections::HashMap; +impl Solution { + pub fn smaller_numbers_than_current(nums: Vec) -> Vec { + let mut v = nums.clone(); + v.sort(); + let mut hash = HashMap::new(); + for i in 0..v.len() { + // rust中使用or_insert插入值, 如果存在就不插入,可以使用正序遍历 + hash.entry(v[i]).or_insert(i as i32); + } + nums.into_iter().map(|x| *hash.get(&x).unwrap()).collect() + } +} +```

From 30685b815cc8787fd84d760045a4e26456a51ef7 Mon Sep 17 00:00:00 2001 From: "junjie2.luo" Date: Thu, 10 Oct 2024 17:19:43 +0800 Subject: [PATCH 17/65] =?UTF-8?q?feat:=200941.=E6=9C=89=E6=95=88=E7=9A=84?= =?UTF-8?q?=E5=B1=B1=E8=84=89=E6=95=B0=E7=BB=84,=E6=96=B0=E5=A2=9Erust?= =?UTF-8?q?=E8=A7=A3=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0941.有效的山脉数组.md | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/problems/0941.有效的山脉数组.md b/problems/0941.有效的山脉数组.md index 9f63f441..77167df0 100644 --- a/problems/0941.有效的山脉数组.md +++ b/problems/0941.有效的山脉数组.md @@ -196,7 +196,22 @@ public class Solution { } ``` - +### Rust +```rust +impl Solution { + pub fn valid_mountain_array(arr: Vec) -> bool { + let mut i = 0; + let mut j = arr.len() - 1; + while i < arr.len() - 1 && arr[i] < arr[i + 1] { + i += 1; + } + while j > 0 && arr[j] < arr[j - 1] { + j -= 1; + } + i > 0 && j < arr.len() - 1 && i == j + } +} +```

From 83de8ac2a1e3f6203f25e5b792acb22bc187676d Mon Sep 17 00:00:00 2001 From: "junjie2.luo" Date: Thu, 10 Oct 2024 17:25:53 +0800 Subject: [PATCH 18/65] =?UTF-8?q?feat:=200283.=E7=A7=BB=E5=8A=A8=E9=9B=B6,?= =?UTF-8?q?=E6=96=B0=E5=A2=9Erust=E8=A7=A3=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0283.移动零.md | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/problems/0283.移动零.md b/problems/0283.移动零.md index 4d8fd9a1..cbce0295 100644 --- a/problems/0283.移动零.md +++ b/problems/0283.移动零.md @@ -169,7 +169,20 @@ void moveZeroes(int* nums, int numsSize){ } ``` - +### Rust +```rust +impl Solution { + pub fn move_zeroes(nums: &mut Vec) { + let mut slow = 0; + for fast in 0..nums.len() { + if nums[fast] != 0 { + nums.swap(slow, fast); + slow += 1; + } + } + } +} +``` From 90255b837ceb114caefd6a5e57eddadf2e0ace61 Mon Sep 17 00:00:00 2001 From: "junjie2.luo" Date: Thu, 10 Oct 2024 17:31:49 +0800 Subject: [PATCH 19/65] =?UTF-8?q?feat:=200189.=E6=97=8B=E8=BD=AC=E6=95=B0?= =?UTF-8?q?=E7=BB=84,=E6=96=B0=E5=A2=9Erust=E8=A7=A3=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0189.旋转数组.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/problems/0189.旋转数组.md b/problems/0189.旋转数组.md index b47ee4b9..e91109c6 100644 --- a/problems/0189.旋转数组.md +++ b/problems/0189.旋转数组.md @@ -199,7 +199,17 @@ function reverseByRange(nums: number[], left: number, right: number): void { } ``` - +### Rust +```rust +impl Solution { + pub fn rotate(nums: &mut Vec, k: i32) { + let k = k as usize % nums.len(); + nums.reverse(); + nums[..k].reverse(); + nums[k..].reverse(); + } +} +```

From a45758ef5f629807e248ea87407611bcbf42ed88 Mon Sep 17 00:00:00 2001 From: iYaovo <2293257241@qq.com> Date: Fri, 11 Oct 2024 10:13:18 +0800 Subject: [PATCH 20/65] =?UTF-8?q?docs:=E8=A1=A5=E5=85=850046Java=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E7=9A=84return=E8=AF=AD=E5=8F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0046.全排列.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/problems/0046.全排列.md b/problems/0046.全排列.md index 1ef80a14..ab7af3ba 100644 --- a/problems/0046.全排列.md +++ b/problems/0046.全排列.md @@ -201,6 +201,7 @@ class Solution { public void backtrack(int[] nums, LinkedList path) { if (path.size() == nums.length) { result.add(new ArrayList<>(path)); + return; } for (int i =0; i < nums.length; i++) { // 如果path中已有,则跳过 @@ -524,3 +525,4 @@ public class Solution + From 55239579183ffebf29c7cfae52c626b996676061 Mon Sep 17 00:00:00 2001 From: markwang Date: Sat, 12 Oct 2024 10:10:05 +0800 Subject: [PATCH 21/65] =?UTF-8?q?122.=E4=B9=B0=E5=8D=96=E8=82=A1=E7=A5=A8?= =?UTF-8?q?=E7=9A=84=E6=9C=80=E4=BD=B3=E6=97=B6=E6=9C=BAII=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0Go=E5=8A=A8=E6=80=81=E8=A7=84=E5=88=92=E6=BB=9A?= =?UTF-8?q?=E5=8A=A8=E6=95=B0=E7=BB=84=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...票的最佳时机II(动态规划).md | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/problems/0122.买卖股票的最佳时机II(动态规划).md b/problems/0122.买卖股票的最佳时机II(动态规划).md index f0dff505..0dced9ef 100644 --- a/problems/0122.买卖股票的最佳时机II(动态规划).md +++ b/problems/0122.买卖股票的最佳时机II(动态规划).md @@ -251,6 +251,27 @@ func max(a, b int) int { } ``` +```go +// 动态规划 版本二 滚动数组 +func maxProfit(prices []int) int { + dp := [2][2]int{} // 注意这里只开辟了一个2 * 2大小的二维数组 + dp[0][0] = -prices[0] + dp[0][1] = 0 + for i := 1; i < len(prices); i++ { + dp[i%2][0] = max(dp[(i-1)%2][0], dp[(i - 1) % 2][1] - prices[i]) + dp[i%2][1] = max(dp[(i-1)%2][1], dp[(i-1)%2][0] + prices[i]) + } + return dp[(len(prices)-1)%2][1] +} + +func max(x, y int) int { + if x > y { + return x + } + return y +} +``` + ### JavaScript: ```javascript From 19a6a4e369277cd192f6b149b008ce2d0cba23a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lane=20Zhang=20=28=E5=BC=A0=E5=81=A5=29?= Date: Mon, 14 Oct 2024 10:00:24 +0800 Subject: [PATCH 22/65] =?UTF-8?q?Update=200202.=E5=BF=AB=E4=B9=90=E6=95=B0?= =?UTF-8?q?.md=20=E5=A2=9E=E5=8A=A0=20Ruby=20=E7=89=88=E6=9C=AC=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0202.快乐数.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/problems/0202.快乐数.md b/problems/0202.快乐数.md index 409a7471..39cb39fa 100644 --- a/problems/0202.快乐数.md +++ b/problems/0202.快乐数.md @@ -534,6 +534,30 @@ public class Solution { } ``` +### Ruby: + +```ruby +# @param {Integer} n +# @return {Boolean} +def is_happy(n) + @occurred_nums = Set.new + + while true + n = next_value(n) + + return true if n == 1 + + return false if @occurred_nums.include?(n) + + @occurred_nums << n + end +end + +def next_value(n) + n.to_s.chars.sum { |char| char.to_i ** 2 } +end +``` +

From c6b12f2b18eb3df0606b39c386e5e441394e81b0 Mon Sep 17 00:00:00 2001 From: markwang Date: Mon, 14 Oct 2024 10:10:19 +0800 Subject: [PATCH 23/65] =?UTF-8?q?123.=E4=B9=B0=E5=8D=96=E8=82=A1=E7=A5=A8?= =?UTF-8?q?=E7=9A=84=E6=9C=80=E4=BD=B3=E6=97=B6=E6=9C=BAIII=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0Go=E7=89=88=E6=9C=AC=E4=BA=8C=E5=92=8C=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E4=B8=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../0123.买卖股票的最佳时机III.md | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/problems/0123.买卖股票的最佳时机III.md b/problems/0123.买卖股票的最佳时机III.md index d06b4f80..8e224a89 100644 --- a/problems/0123.买卖股票的最佳时机III.md +++ b/problems/0123.买卖股票的最佳时机III.md @@ -317,6 +317,7 @@ class Solution: ### Go: ```go +// 版本一 func maxProfit(prices []int) int { dp := make([][]int, len(prices)) for i := 0; i < len(prices); i++ { @@ -344,6 +345,58 @@ func max(a, b int) int { } ``` +```go +// 版本二 +func maxProfit(prices []int) int { + if len(prices) == 0 { + return 0 + } + dp := make([]int, 5) + dp[1] = -prices[0] + dp[3] = -prices[0] + for i := 1; i < len(prices); i++ { + dp[1] = max(dp[1], dp[0] - prices[i]) + dp[2] = max(dp[2], dp[1] + prices[i]) + dp[3] = max(dp[3], dp[2] - prices[i]) + dp[4] = max(dp[4], dp[3] + prices[i]) + } + return dp[4] +} + +func max(x, y int) int { + if x > y { + return x + } + return y +} +``` + +```go +// 版本三 +func maxProfit(prices []int) int { + if len(prices) == 0 { + return 0 + } + dp := make([][5]int, len(prices)) + dp[0][1] = -prices[0] + dp[0][3] = -prices[0] + for i := 1; i < len(prices); i++ { + dp[i][1] = max(dp[i-1][1], 0 - prices[i]) + dp[i][2] = max(dp[i-1][2], dp[i-1][1] + prices[i]) + dp[i][3] = max(dp[i-1][3], dp[i-1][2] - prices[i]) + dp[i][4] = max(dp[i-1][4], dp[i-1][3] + prices[i]) + } + return dp[len(prices)-1][4] +} + +func max(x, y int) int { + if x > y { + return x + } + return y +} +``` + ### JavaScript: > 版本一: From 0be8c49ba72d9e3e6ccdc4b76949a07ae128b7d5 Mon Sep 17 00:00:00 2001 From: markwang Date: Tue, 15 Oct 2024 09:49:57 +0800 Subject: [PATCH 24/65] =?UTF-8?q?0714.=E4=B9=B0=E5=8D=96=E8=82=A1=E7=A5=A8?= =?UTF-8?q?=E7=9A=84=E6=9C=80=E4=BD=B3=E6=97=B6=E6=9C=BA=E5=90=AB=E6=89=8B?= =?UTF-8?q?=E7=BB=AD=E8=B4=B9=E6=96=87=E5=AD=97=E5=8B=98=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0714.买卖股票的最佳时机含手续费.md | 4 ++-- ...卖股票的最佳时机含手续费(动态规划).md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/problems/0714.买卖股票的最佳时机含手续费.md b/problems/0714.买卖股票的最佳时机含手续费.md index 88b03d9d..8a2d976b 100644 --- a/problems/0714.买卖股票的最佳时机含手续费.md +++ b/problems/0714.买卖股票的最佳时机含手续费.md @@ -43,7 +43,7 @@ 在[贪心算法:122.买卖股票的最佳时机II](https://programmercarl.com/0122.买卖股票的最佳时机II.html)中使用贪心策略不用关心具体什么时候买卖,只要收集每天的正利润,最后稳稳的就是最大利润了。 -而本题有了手续费,就要关系什么时候买卖了,因为计算所获得利润,需要考虑买卖利润可能不足以手续费的情况。 +而本题有了手续费,就要关心什么时候买卖了,因为计算所获得利润,需要考虑买卖利润可能不足以扣减手续费的情况。 如果使用贪心策略,就是最低值买,最高值(如果算上手续费还盈利)就卖。 @@ -122,7 +122,7 @@ public: * 时间复杂度:O(n) * 空间复杂度:O(n) -当然可以对空间经行优化,因为当前状态只是依赖前一个状态。 +当然可以对空间进行优化,因为当前状态只是依赖前一个状态。 C++ 代码如下: diff --git a/problems/0714.买卖股票的最佳时机含手续费(动态规划).md b/problems/0714.买卖股票的最佳时机含手续费(动态规划).md index b0e8b141..86e3e88f 100644 --- a/problems/0714.买卖股票的最佳时机含手续费(动态规划).md +++ b/problems/0714.买卖股票的最佳时机含手续费(动态规划).md @@ -46,7 +46,7 @@ * 时间复杂度:O(n) * 空间复杂度:O(1) -本题使用贪心算法并不好理解,也很容易出错,那么我们再来看看是使用动规的方法如何解题。 +本题使用贪心算法并不好理解,也很容易出错,那么我们再来看看使用动规的方法如何解题。 相对于[动态规划:122.买卖股票的最佳时机II](https://programmercarl.com/0122.买卖股票的最佳时机II(动态规划).html),本题只需要在计算卖出操作的时候减去手续费就可以了,代码几乎是一样的。 @@ -54,7 +54,7 @@ 这里重申一下dp数组的含义: -dp[i][0] 表示第i天持有股票所省最多现金。 +dp[i][0] 表示第i天持有股票所得最多现金。 dp[i][1] 表示第i天不持有股票所得最多现金 From abd3593c67a551bbe01136a42defabf219bb55be Mon Sep 17 00:00:00 2001 From: Lane Zhang Date: Tue, 15 Oct 2024 13:30:09 +0800 Subject: [PATCH 25/65] =?UTF-8?q?0454.=E5=9B=9B=E6=95=B0=E7=9B=B8=E5=8A=A0?= =?UTF-8?q?II.html=20=E5=A2=9E=E5=8A=A0Ruby=E7=89=88=E6=9C=AC=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0454.四数相加II.md | 38 +++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/problems/0454.四数相加II.md b/problems/0454.四数相加II.md index 6231c22b..af19f5f7 100644 --- a/problems/0454.四数相加II.md +++ b/problems/0454.四数相加II.md @@ -488,6 +488,44 @@ int fourSumCount(int* nums1, int nums1Size, int* nums2, int nums2Size, int* nums } ``` +### Ruby: + +```ruby +# @param {Integer[]} nums1 +# @param {Integer[]} nums2 +# @param {Integer[]} nums3 +# @param {Integer[]} nums4 +# @return {Integer} +# 新思路:和版主的思路基本相同,只是对后面两个数组的二重循环,用一个方法调用外加一重循环替代,简化了一点。 +# 简单的说,就是把四数和变成了两个两数和的统计(结果放到两个 hash 中),然后再来一次两数和为0. +# 把四个数分成两组两个数,然后分别计算每组可能的和情况,分别存入 hash 中,key 是 和,value 是 数量; +# 最后,得到的两个 hash 只需要遍历一次,符合和为零的 value 相乘并加总。 +def four_sum_count(nums1, nums2, nums3, nums4) + num_to_count_1 = two_sum_mapping(nums1, nums2) + num_to_count_2 = two_sum_mapping(nums3, nums4) + + count_sum = 0 + + num_to_count_1.each do |num, count| + count_sum += num_to_count_2[-num] * count # 反查另一个 hash,看有没有匹配的,没有的话,hash 默认值为 0,不影响加总;有匹配的,乘积就是可能的情况 + end + + count_sum +end + +def two_sum_mapping(nums1, nums2) + num_to_count = Hash.new(0) + + nums1.each do |num1| + nums2.each do |nums2| + num_to_count[num1 + nums2] += 1 # 统计和为 num1 + nums2 的有几个 + end + end + + num_to_count +end +``` +

From a4cafe0ce750c44f327a97a9811ff0b2d2c49979 Mon Sep 17 00:00:00 2001 From: Lane Zhang Date: Wed, 16 Oct 2024 11:25:49 +0800 Subject: [PATCH 26/65] =?UTF-8?q?0541.=E5=8F=8D=E8=BD=AC=E5=AD=97=E7=AC=A6?= =?UTF-8?q?=E4=B8=B2II.md=20=E5=A2=9E=E5=8A=A0Python=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E5=AE=9E=E7=8E=B03?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0541.反转字符串II.md | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/problems/0541.反转字符串II.md b/problems/0541.反转字符串II.md index 5e75d3c3..c89b3a7b 100644 --- a/problems/0541.反转字符串II.md +++ b/problems/0541.反转字符串II.md @@ -282,7 +282,7 @@ class Solution: return ''.join(res) ``` -### Python3 (v2): +#### Python3 (v2): ```python class Solution: @@ -297,6 +297,20 @@ class Solution: return s ``` +#### Python3 (v3): +```python +class Solution: + def reverseStr(self, s: str, k: int) -> str: + i = 0 + chars = list(s) + + while i < len(chars): + chars[i:i + k] = chars[i:i + k][::-1] # 反转后,更改原值为反转后值 + i += k * 2 + + return ''.join(chars) +``` + ### Go: ```go From 27585bd4f8fc7b4f0599f231d4924641e1bf6deb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lane=20Zhang=20=28=E5=BC=A0=E5=81=A5=29?= Date: Wed, 16 Oct 2024 11:27:38 +0800 Subject: [PATCH 27/65] =?UTF-8?q?Update=200541.=E5=8F=8D=E8=BD=AC=E5=AD=97?= =?UTF-8?q?=E7=AC=A6=E4=B8=B2II.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0541.反转字符串II.md | 1 + 1 file changed, 1 insertion(+) diff --git a/problems/0541.反转字符串II.md b/problems/0541.反转字符串II.md index c89b3a7b..b3e7b022 100644 --- a/problems/0541.反转字符串II.md +++ b/problems/0541.反转字符串II.md @@ -298,6 +298,7 @@ class Solution: ``` #### Python3 (v3): + ```python class Solution: def reverseStr(self, s: str, k: int) -> str: From cb50b956ebc89019b915ce92174126f82de10e1a Mon Sep 17 00:00:00 2001 From: ch4r1ty <81227726+ch4r1ty@users.noreply.github.com> Date: Wed, 16 Oct 2024 00:01:58 -0400 Subject: [PATCH 28/65] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E4=BA=860027.=E7=A7=BB?= =?UTF-8?q?=E9=99=A4=E5=85=83=E7=B4=A0.md=EF=BC=8C=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E4=BA=86java=E6=9A=B4=E5=8A=9B=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0027.移除元素.md | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/problems/0027.移除元素.md b/problems/0027.移除元素.md index 480800e9..10817ba6 100644 --- a/problems/0027.移除元素.md +++ b/problems/0027.移除元素.md @@ -131,7 +131,24 @@ public: ## 其他语言版本 ### Java: - +```java +class Solution { + public int removeElement(int[] nums, int val) { + // 暴力法 + int n = nums.length; + for (int i = 0; i < n; i++) { + if (nums[i] == val) { + for (int j = i + 1; j < n; j++) { + nums[j - 1] = nums[j]; + } + i--; + n--; + } + } + return n; + } +} +``` ```java class Solution { public int removeElement(int[] nums, int val) { From 7bbf3827d1b9aa3a18f4073533ac2934ecc4eab1 Mon Sep 17 00:00:00 2001 From: Lane Zhang Date: Wed, 16 Oct 2024 14:20:41 +0800 Subject: [PATCH 29/65] =?UTF-8?q?0151.=E7=BF=BB=E8=BD=AC=E5=AD=97=E7=AC=A6?= =?UTF-8?q?=E4=B8=B2=E9=87=8C=E7=9A=84=E5=8D=95=E8=AF=8D=20=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0Python=E7=89=88=E6=9C=AC=E5=AE=9E=E7=8E=B05?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0151.翻转字符串里的单词.md | 23 ++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/problems/0151.翻转字符串里的单词.md b/problems/0151.翻转字符串里的单词.md index 9a0cbea4..7c0b7cb1 100644 --- a/problems/0151.翻转字符串里的单词.md +++ b/problems/0151.翻转字符串里的单词.md @@ -513,6 +513,29 @@ class Solution: return "".join(result) ``` + +(版本五) 遇到空格就说明前面的是一个单词,把它加入到一个数组中。 + +```python +class Solution: + def reverseWords(self, s: str) -> str: + words = [] + word = '' + s += ' ' # 帮助处理最后一个字词 + + for char in s: + if char == ' ': # 遇到空格就说明前面的可能是一个单词 + if word != '': # 确认是单词,把它加入到一个数组中 + words.append(word) + word = '' # 清空当前单词 + continue + + word += char # 收集单词的字母 + + words.reverse() + return ' '.join(words) +``` + ### Go: 版本一: From ee4c1c584cbe27ff27f4dbf0cdb858c38d574171 Mon Sep 17 00:00:00 2001 From: skyclouds2001 <95597335+skyclouds2001@users.noreply.github.com> Date: Thu, 17 Oct 2024 00:27:53 +0800 Subject: [PATCH 30/65] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E6=8B=BC=E5=86=99?= =?UTF-8?q?=EF=BC=9AJavascript->JavaScript&Typescript->TypeScript?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0001.两数之和.md | 2 +- problems/0020.有效的括号.md | 2 +- problems/0024.两两交换链表中的节点.md | 2 +- problems/0037.解数独.md | 2 +- problems/0045.跳跃游戏II.md | 2 +- problems/0046.全排列.md | 2 +- problems/0047.全排列II.md | 2 +- problems/0051.N皇后.md | 2 +- problems/0053.最大子序和.md | 2 +- problems/0054.螺旋矩阵.md | 2 +- problems/0055.跳跃游戏.md | 2 +- problems/0056.合并区间.md | 2 +- problems/0062.不同路径.md | 2 +- problems/0063.不同路径II.md | 2 +- problems/0070.爬楼梯.md | 2 +- problems/0072.编辑距离.md | 2 +- problems/0077.组合.md | 2 +- problems/0078.子集.md | 2 +- problems/0090.子集II.md | 2 +- problems/0096.不同的二叉搜索树.md | 2 +- problems/0102.二叉树的层序遍历.md | 10 +++++----- problems/0104.二叉树的最大深度.md | 2 +- problems/0112.路径总和.md | 2 +- problems/0115.不同的子序列.md | 2 +- problems/0122.买卖股票的最佳时机II.md | 2 +- problems/0134.加油站.md | 2 +- problems/0135.分发糖果.md | 2 +- problems/0209.长度最小的子数组.md | 2 +- problems/0239.滑动窗口最大值.md | 2 +- problems/0279.完全平方数.md | 2 +- problems/0300.最长上升子序列.md | 2 +- problems/0309.最佳买卖股票时机含冷冻期.md | 2 +- problems/0322.零钱兑换.md | 2 +- problems/0332.重新安排行程.md | 2 +- problems/0343.整数拆分.md | 2 +- problems/0376.摆动序列.md | 2 +- problems/0377.组合总和Ⅳ.md | 2 +- problems/0406.根据身高重建队列.md | 2 +- problems/0435.无重叠区间.md | 2 +- problems/0452.用最少数量的箭引爆气球.md | 2 +- problems/0455.分发饼干.md | 2 +- problems/0474.一和零.md | 2 +- problems/0491.递增子序列.md | 2 +- problems/0494.目标和.md | 2 +- problems/0509.斐波那契数.md | 2 +- problems/0516.最长回文子序列.md | 2 +- problems/0518.零钱兑换II.md | 2 +- problems/0583.两个字符串的删除操作.md | 2 +- problems/0647.回文子串.md | 2 +- problems/0674.最长连续递增序列.md | 2 +- .../0714.买卖股票的最佳时机含手续费.md | 2 +- ...票的最佳时机含手续费(动态规划).md | 2 +- problems/0738.单调递增的数字.md | 2 +- problems/0763.划分字母区间.md | 2 +- problems/0860.柠檬水找零.md | 2 +- problems/0968.监控二叉树.md | 2 +- problems/0977.有序数组的平方.md | 4 ++-- problems/1005.K次取反后最大化的数组和.md | 2 +- problems/1971.寻找图中是否存在路径.md | 2 +- problems/kamacoder/0047.参会dijkstra堆.md | 2 +- problems/kamacoder/0047.参会dijkstra朴素.md | 2 +- problems/kamacoder/0053.寻宝-Kruskal.md | 2 +- problems/kamacoder/0053.寻宝-prim.md | 2 +- problems/kamacoder/0094.城市间货物运输I-SPFA.md | 2 +- problems/kamacoder/0094.城市间货物运输I.md | 2 +- problems/kamacoder/0095.城市间货物运输II.md | 2 +- problems/kamacoder/0096.城市间货物运输III.md | 2 +- problems/kamacoder/0097.小明逛公园.md | 2 +- problems/kamacoder/0098.所有可达路径.md | 2 +- problems/kamacoder/0099.岛屿的数量广搜.md | 2 +- problems/kamacoder/0099.岛屿的数量深搜.md | 2 +- problems/kamacoder/0100.岛屿的最大面积.md | 2 +- problems/kamacoder/0101.孤岛的总面积.md | 2 +- problems/kamacoder/0102.沉没孤岛.md | 2 +- problems/kamacoder/0103.水流问题.md | 2 +- problems/kamacoder/0104.建造最大岛屿.md | 2 +- problems/kamacoder/0105.有向图的完全可达性.md | 2 +- problems/kamacoder/0106.岛屿的周长.md | 2 +- problems/kamacoder/0107.寻找存在的路径.md | 2 +- problems/kamacoder/0108.冗余连接.md | 2 +- problems/kamacoder/0109.冗余连接II.md | 2 +- problems/kamacoder/0110.字符串接龙.md | 2 +- problems/kamacoder/0117.软件构建.md | 2 +- problems/kamacoder/0126.骑士的攻击astar.md | 2 +- problems/二叉树的递归遍历.md | 2 +- problems/背包理论基础01背包-1.md | 2 +- problems/背包问题理论基础完全背包.md | 2 +- 87 files changed, 92 insertions(+), 92 deletions(-) diff --git a/problems/0001.两数之和.md b/problems/0001.两数之和.md index 044eac14..e982ae12 100644 --- a/problems/0001.两数之和.md +++ b/problems/0001.两数之和.md @@ -341,7 +341,7 @@ impl Solution { } ``` -### Javascript: +### JavaScript: ```javascript var twoSum = function (nums, target) { diff --git a/problems/0020.有效的括号.md b/problems/0020.有效的括号.md index d310f415..f2f5cdd1 100644 --- a/problems/0020.有效的括号.md +++ b/problems/0020.有效的括号.md @@ -275,7 +275,7 @@ def is_valid(strs) end ``` -### Javascript: +### JavaScript: ```javascript var isValid = function (s) { diff --git a/problems/0024.两两交换链表中的节点.md b/problems/0024.两两交换链表中的节点.md index 23dba84b..305bb7cc 100644 --- a/problems/0024.两两交换链表中的节点.md +++ b/problems/0024.两两交换链表中的节点.md @@ -286,7 +286,7 @@ func swapPairs(head *ListNode) *ListNode { } ``` -### Javascript: +### JavaScript: ```javascript var swapPairs = function (head) { diff --git a/problems/0037.解数独.md b/problems/0037.解数独.md index 70d52e9e..6a9f69bd 100644 --- a/problems/0037.解数独.md +++ b/problems/0037.解数独.md @@ -460,7 +460,7 @@ func isvalid(row, col int, k byte, board [][]byte) bool { -### Javascript +### JavaScript ```Javascript var solveSudoku = function(board) { diff --git a/problems/0045.跳跃游戏II.md b/problems/0045.跳跃游戏II.md index 3eeec268..8919d393 100644 --- a/problems/0045.跳跃游戏II.md +++ b/problems/0045.跳跃游戏II.md @@ -374,7 +374,7 @@ func max(a, b int) int { } ``` -### Javascript +### JavaScript ```Javascript var jump = function(nums) { diff --git a/problems/0046.全排列.md b/problems/0046.全排列.md index 1ef80a14..4302bdbf 100644 --- a/problems/0046.全排列.md +++ b/problems/0046.全排列.md @@ -271,7 +271,7 @@ func dfs(nums []int, cur int) { } ``` -### Javascript +### JavaScript ```js diff --git a/problems/0047.全排列II.md b/problems/0047.全排列II.md index 56006a77..08e3c616 100644 --- a/problems/0047.全排列II.md +++ b/problems/0047.全排列II.md @@ -283,7 +283,7 @@ func dfs(nums []int, cur int) { } ``` -### Javascript +### JavaScript ```javascript var permuteUnique = function (nums) { diff --git a/problems/0051.N皇后.md b/problems/0051.N皇后.md index 6ced679c..38fc07e7 100644 --- a/problems/0051.N皇后.md +++ b/problems/0051.N皇后.md @@ -451,7 +451,7 @@ func isValid(n, row, col int, chessboard [][]string) bool { ``` -### Javascript +### JavaScript ```Javascript /** * @param {number} n diff --git a/problems/0053.最大子序和.md b/problems/0053.最大子序和.md index 1c7ff0cd..69a7d190 100644 --- a/problems/0053.最大子序和.md +++ b/problems/0053.最大子序和.md @@ -290,7 +290,7 @@ pub fn max_sub_array(nums: Vec) -> i32 { } ``` -### Javascript: +### JavaScript: ```Javascript var maxSubArray = function(nums) { diff --git a/problems/0054.螺旋矩阵.md b/problems/0054.螺旋矩阵.md index 6c0bad40..3b7afb90 100644 --- a/problems/0054.螺旋矩阵.md +++ b/problems/0054.螺旋矩阵.md @@ -260,7 +260,7 @@ class Solution { } ``` -### Javascript +### JavaScript ``` /** * @param {number[][]} matrix diff --git a/problems/0055.跳跃游戏.md b/problems/0055.跳跃游戏.md index 01fd9513..cbbf5980 100644 --- a/problems/0055.跳跃游戏.md +++ b/problems/0055.跳跃游戏.md @@ -166,7 +166,7 @@ func max(a, b int ) int { } ``` -### Javascript +### JavaScript ```Javascript var canJump = function(nums) { diff --git a/problems/0056.合并区间.md b/problems/0056.合并区间.md index 134a9028..538be693 100644 --- a/problems/0056.合并区间.md +++ b/problems/0056.合并区间.md @@ -215,7 +215,7 @@ func max56(a, b int) int { ``` -### Javascript +### JavaScript ```javascript var merge = function (intervals) { intervals.sort((a, b) => a[0] - b[0]); diff --git a/problems/0062.不同路径.md b/problems/0062.不同路径.md index 5b46caa9..7025135a 100644 --- a/problems/0062.不同路径.md +++ b/problems/0062.不同路径.md @@ -411,7 +411,7 @@ func uniquePaths(m int, n int) int { } ``` -### Javascript +### JavaScript ```Javascript var uniquePaths = function(m, n) { diff --git a/problems/0063.不同路径II.md b/problems/0063.不同路径II.md index daf3d8c5..13923abe 100644 --- a/problems/0063.不同路径II.md +++ b/problems/0063.不同路径II.md @@ -465,7 +465,7 @@ func uniquePathsWithObstacles(obstacleGrid [][]int) int { } ``` -### Javascript +### JavaScript ```Javascript var uniquePathsWithObstacles = function(obstacleGrid) { diff --git a/problems/0070.爬楼梯.md b/problems/0070.爬楼梯.md index 1d0b192f..a2f664a4 100644 --- a/problems/0070.爬楼梯.md +++ b/problems/0070.爬楼梯.md @@ -327,7 +327,7 @@ func climbStairs(n int) int { return dp[n] } ``` -### Javascript +### JavaScript ```Javascript var climbStairs = function(n) { // dp[i] 为第 i 阶楼梯有多少种方法爬到楼顶 diff --git a/problems/0072.编辑距离.md b/problems/0072.编辑距离.md index b8de8bdc..0da3bf50 100644 --- a/problems/0072.编辑距离.md +++ b/problems/0072.编辑距离.md @@ -313,7 +313,7 @@ func Min(args ...int) int { } ``` -### Javascript: +### JavaScript: ```javascript const minDistance = (word1, word2) => { diff --git a/problems/0077.组合.md b/problems/0077.组合.md index 3a271ff8..c4be5a38 100644 --- a/problems/0077.组合.md +++ b/problems/0077.组合.md @@ -468,7 +468,7 @@ func dfs(n int, k int, start int) { } ``` -### Javascript +### JavaScript 未剪枝: ```js diff --git a/problems/0078.子集.md b/problems/0078.子集.md index 723d99a1..0c368b41 100644 --- a/problems/0078.子集.md +++ b/problems/0078.子集.md @@ -246,7 +246,7 @@ func dfs(nums []int, start int) { } ``` -### Javascript +### JavaScript ```Javascript var subsets = function(nums) { diff --git a/problems/0090.子集II.md b/problems/0090.子集II.md index 939ef369..811d3cc0 100644 --- a/problems/0090.子集II.md +++ b/problems/0090.子集II.md @@ -376,7 +376,7 @@ func dfs(nums []int, start int) { ``` -### Javascript +### JavaScript ```Javascript diff --git a/problems/0096.不同的二叉搜索树.md b/problems/0096.不同的二叉搜索树.md index e0e77310..25d79aff 100644 --- a/problems/0096.不同的二叉搜索树.md +++ b/problems/0096.不同的二叉搜索树.md @@ -221,7 +221,7 @@ func numTrees(n int)int{ } ``` -### Javascript +### JavaScript ```Javascript const numTrees =(n) => { diff --git a/problems/0102.二叉树的层序遍历.md b/problems/0102.二叉树的层序遍历.md index cad32414..98e1e98a 100644 --- a/problems/0102.二叉树的层序遍历.md +++ b/problems/0102.二叉树的层序遍历.md @@ -356,7 +356,7 @@ func levelOrder(root *TreeNode) (res [][]int) { } ``` -#### Javascript: +#### JavaScript: ```javascript var levelOrder = function(root) { @@ -759,7 +759,7 @@ func levelOrderBottom(root *TreeNode) [][]int { } ``` -#### Javascript: +#### JavaScript: ```javascript var levelOrderBottom = function (root) { @@ -1101,7 +1101,7 @@ func rightSideView(root *TreeNode) []int { } ``` -#### Javascript: +#### JavaScript: ```javascript var rightSideView = function(root) { @@ -1421,7 +1421,7 @@ func averageOfLevels(root *TreeNode) []float64 { } ``` -#### Javascript: +#### JavaScript: ```javascript var averageOfLevels = function(root) { @@ -2109,7 +2109,7 @@ func largestValues(root *TreeNode) []int { } ``` -#### Javascript: +#### JavaScript: ```javascript var largestValues = function (root) { diff --git a/problems/0104.二叉树的最大深度.md b/problems/0104.二叉树的最大深度.md index 607e195b..fdc90096 100644 --- a/problems/0104.二叉树的最大深度.md +++ b/problems/0104.二叉树的最大深度.md @@ -604,7 +604,7 @@ func maxDepth(root *Node) int { } ``` -### Javascript : +### JavaScript : 104.二叉树的最大深度 diff --git a/problems/0112.路径总和.md b/problems/0112.路径总和.md index e6ccc6ae..b97013e6 100644 --- a/problems/0112.路径总和.md +++ b/problems/0112.路径总和.md @@ -830,7 +830,7 @@ func traverse(node *TreeNode, result *[][]int, currPath *[]int, targetSum int) { } ``` -### Javascript +### JavaScript 0112.路径总和 diff --git a/problems/0115.不同的子序列.md b/problems/0115.不同的子序列.md index 8682b88d..cf24c4c1 100644 --- a/problems/0115.不同的子序列.md +++ b/problems/0115.不同的子序列.md @@ -265,7 +265,7 @@ func numDistinct(s string, t string) int { } ``` -### Javascript: +### JavaScript: ```javascript const numDistinct = (s, t) => { diff --git a/problems/0122.买卖股票的最佳时机II.md b/problems/0122.买卖股票的最佳时机II.md index e255723d..6663a66d 100644 --- a/problems/0122.买卖股票的最佳时机II.md +++ b/problems/0122.买卖股票的最佳时机II.md @@ -249,7 +249,7 @@ func max(a, b int) int { } ``` -### Javascript: +### JavaScript: 贪心 diff --git a/problems/0134.加油站.md b/problems/0134.加油站.md index 5cf50b3e..0248760d 100644 --- a/problems/0134.加油站.md +++ b/problems/0134.加油站.md @@ -396,7 +396,7 @@ func canCompleteCircuit(gas []int, cost []int) int { } ``` -### Javascript +### JavaScript 暴力: ```js var canCompleteCircuit = function(gas, cost) { diff --git a/problems/0135.分发糖果.md b/problems/0135.分发糖果.md index 6805857e..177d23e7 100644 --- a/problems/0135.分发糖果.md +++ b/problems/0135.分发糖果.md @@ -234,7 +234,7 @@ func findMax(num1 int, num2 int) int { } ``` -### Javascript +### JavaScript ```Javascript var candy = function(ratings) { let candys = new Array(ratings.length).fill(1) diff --git a/problems/0209.长度最小的子数组.md b/problems/0209.长度最小的子数组.md index e399ac90..c6d89976 100644 --- a/problems/0209.长度最小的子数组.md +++ b/problems/0209.长度最小的子数组.md @@ -266,7 +266,7 @@ var minSubArrayLen = function(target, nums) { }; ``` -### Typescript: +### TypeScript: ```typescript function minSubArrayLen(target: number, nums: number[]): number { diff --git a/problems/0239.滑动窗口最大值.md b/problems/0239.滑动窗口最大值.md index 23bf615b..9c71778f 100644 --- a/problems/0239.滑动窗口最大值.md +++ b/problems/0239.滑动窗口最大值.md @@ -401,7 +401,7 @@ func maxSlidingWindow(nums []int, k int) []int { } ``` -### Javascript: +### JavaScript: ```javascript /** diff --git a/problems/0279.完全平方数.md b/problems/0279.完全平方数.md index 570632bd..dc5a7e9e 100644 --- a/problems/0279.完全平方数.md +++ b/problems/0279.完全平方数.md @@ -346,7 +346,7 @@ func min(a, b int) int { } ``` -### Javascript: +### JavaScript: ```Javascript // 先遍历物品,再遍历背包 diff --git a/problems/0300.最长上升子序列.md b/problems/0300.最长上升子序列.md index f1a146b7..442938c0 100644 --- a/problems/0300.最长上升子序列.md +++ b/problems/0300.最长上升子序列.md @@ -248,7 +248,7 @@ func lengthOfLIS(nums []int ) int { } ``` -### Javascript: +### JavaScript: ```javascript const lengthOfLIS = (nums) => { diff --git a/problems/0309.最佳买卖股票时机含冷冻期.md b/problems/0309.最佳买卖股票时机含冷冻期.md index 4913b8bd..480b0866 100644 --- a/problems/0309.最佳买卖股票时机含冷冻期.md +++ b/problems/0309.最佳买卖股票时机含冷冻期.md @@ -393,7 +393,7 @@ func max(a, b int) int { -### Javascript: +### JavaScript: > 不同的状态定义 感觉更容易理解些 ```javascript diff --git a/problems/0322.零钱兑换.md b/problems/0322.零钱兑换.md index 0ed5cf68..e55e20be 100644 --- a/problems/0322.零钱兑换.md +++ b/problems/0322.零钱兑换.md @@ -427,7 +427,7 @@ impl Solution { } ``` -### Javascript: +### JavaScript: ```javascript // 遍历物品 diff --git a/problems/0332.重新安排行程.md b/problems/0332.重新安排行程.md index 1d9c524b..ed8149d0 100644 --- a/problems/0332.重新安排行程.md +++ b/problems/0332.重新安排行程.md @@ -535,7 +535,7 @@ func findItinerary(tickets [][]string) []string { } ``` -### Javascript +### JavaScript ```Javascript diff --git a/problems/0343.整数拆分.md b/problems/0343.整数拆分.md index 3ba23e52..5d0110f6 100644 --- a/problems/0343.整数拆分.md +++ b/problems/0343.整数拆分.md @@ -385,7 +385,7 @@ func integerBreak(n int) int { } ``` -### Javascript +### JavaScript ```Javascript var integerBreak = function(n) { let dp = new Array(n + 1).fill(0) diff --git a/problems/0376.摆动序列.md b/problems/0376.摆动序列.md index 9e6714ce..9cf1ed8c 100644 --- a/problems/0376.摆动序列.md +++ b/problems/0376.摆动序列.md @@ -466,7 +466,7 @@ func max(a, b int) int { } ``` -### Javascript +### JavaScript **贪心** diff --git a/problems/0377.组合总和Ⅳ.md b/problems/0377.组合总和Ⅳ.md index e96f8dc6..ba8546c6 100644 --- a/problems/0377.组合总和Ⅳ.md +++ b/problems/0377.组合总和Ⅳ.md @@ -254,7 +254,7 @@ func combinationSum4(nums []int, target int) int { } ``` -### Javascript: +### JavaScript: ```javascript const combinationSum4 = (nums, target) => { diff --git a/problems/0406.根据身高重建队列.md b/problems/0406.根据身高重建队列.md index d92a7f3f..d6fc415b 100644 --- a/problems/0406.根据身高重建队列.md +++ b/problems/0406.根据身高重建队列.md @@ -270,7 +270,7 @@ func reconstructQueue(people [][]int) [][]int { } ``` -### Javascript +### JavaScript ```Javascript var reconstructQueue = function(people) { diff --git a/problems/0435.无重叠区间.md b/problems/0435.无重叠区间.md index 20961602..d6321315 100644 --- a/problems/0435.无重叠区间.md +++ b/problems/0435.无重叠区间.md @@ -311,7 +311,7 @@ func min(a, b int) int { } ``` -### Javascript +### JavaScript - 按右边界排序 ```Javascript var eraseOverlapIntervals = function(intervals) { diff --git a/problems/0452.用最少数量的箭引爆气球.md b/problems/0452.用最少数量的箭引爆气球.md index 318c3035..9b9eef1d 100644 --- a/problems/0452.用最少数量的箭引爆气球.md +++ b/problems/0452.用最少数量的箭引爆气球.md @@ -220,7 +220,7 @@ func min(a, b int) int { } ``` -### Javascript +### JavaScript ```Javascript var findMinArrowShots = function(points) { points.sort((a, b) => { diff --git a/problems/0455.分发饼干.md b/problems/0455.分发饼干.md index 22dd7570..5e8fb730 100644 --- a/problems/0455.分发饼干.md +++ b/problems/0455.分发饼干.md @@ -278,7 +278,7 @@ pub fn find_content_children(mut children: Vec, mut cookies: Vec) -> i } ``` -### Javascript +### JavaScript ```js var findContentChildren = function (g, s) { diff --git a/problems/0474.一和零.md b/problems/0474.一和零.md index 72d62243..e514e729 100644 --- a/problems/0474.一和零.md +++ b/problems/0474.一和零.md @@ -362,7 +362,7 @@ func max(a,b int) int { } ``` -### Javascript +### JavaScript ```javascript const findMaxForm = (strs, m, n) => { const dp = Array.from(Array(m+1), () => Array(n+1).fill(0)); diff --git a/problems/0491.递增子序列.md b/problems/0491.递增子序列.md index 8f642a5f..7832095a 100644 --- a/problems/0491.递增子序列.md +++ b/problems/0491.递增子序列.md @@ -375,7 +375,7 @@ func dfs(nums []int, start int) { } ``` -### Javascript +### JavaScript ```Javascript diff --git a/problems/0494.目标和.md b/problems/0494.目标和.md index 08724609..206fdf89 100644 --- a/problems/0494.目标和.md +++ b/problems/0494.目标和.md @@ -791,7 +791,7 @@ func abs(x int) int { } ``` -### Javascript +### JavaScript ```javascript const findTargetSumWays = (nums, target) => { diff --git a/problems/0509.斐波那契数.md b/problems/0509.斐波那契数.md index 21b07802..1c4127fc 100644 --- a/problems/0509.斐波那契数.md +++ b/problems/0509.斐波那契数.md @@ -292,7 +292,7 @@ func fib(n int) int { return c } ``` -### Javascript +### JavaScript 解法一 ```Javascript var fib = function(n) { diff --git a/problems/0516.最长回文子序列.md b/problems/0516.最长回文子序列.md index af36b94d..166310aa 100644 --- a/problems/0516.最长回文子序列.md +++ b/problems/0516.最长回文子序列.md @@ -224,7 +224,7 @@ func longestPalindromeSubseq(s string) int { } ``` -### Javascript: +### JavaScript: ```javascript const longestPalindromeSubseq = (s) => { diff --git a/problems/0518.零钱兑换II.md b/problems/0518.零钱兑换II.md index 70231212..0d35fb7c 100644 --- a/problems/0518.零钱兑换II.md +++ b/problems/0518.零钱兑换II.md @@ -349,7 +349,7 @@ impl Solution { } ``` -### Javascript: +### JavaScript: ```javascript const change = (amount, coins) => { diff --git a/problems/0583.两个字符串的删除操作.md b/problems/0583.两个字符串的删除操作.md index 14a55631..8e63e82c 100644 --- a/problems/0583.两个字符串的删除操作.md +++ b/problems/0583.两个字符串的删除操作.md @@ -287,7 +287,7 @@ func min(a, b int) int { return b } ``` -### Javascript: +### JavaScript: ```javascript // 方法一 diff --git a/problems/0647.回文子串.md b/problems/0647.回文子串.md index 89e4ad11..6f0fea4a 100644 --- a/problems/0647.回文子串.md +++ b/problems/0647.回文子串.md @@ -465,7 +465,7 @@ func countSubstrings(s string) int { } ``` -### Javascript: +### JavaScript: > 动态规划 ```javascript diff --git a/problems/0674.最长连续递增序列.md b/problems/0674.最长连续递增序列.md index 57a38404..8b967092 100644 --- a/problems/0674.最长连续递增序列.md +++ b/problems/0674.最长连续递增序列.md @@ -359,7 +359,7 @@ impl Solution { ``` -### Javascript: +### JavaScript: > 动态规划: ```javascript diff --git a/problems/0714.买卖股票的最佳时机含手续费.md b/problems/0714.买卖股票的最佳时机含手续费.md index 88b03d9d..c87607a2 100644 --- a/problems/0714.买卖股票的最佳时机含手续费.md +++ b/problems/0714.买卖股票的最佳时机含手续费.md @@ -243,7 +243,7 @@ func maxProfit(prices []int, fee int) int { return res } ``` -### Javascript +### JavaScript ```Javascript // 贪心思路 var maxProfit = function(prices, fee) { diff --git a/problems/0714.买卖股票的最佳时机含手续费(动态规划).md b/problems/0714.买卖股票的最佳时机含手续费(动态规划).md index b0e8b141..3f5f929c 100644 --- a/problems/0714.买卖股票的最佳时机含手续费(动态规划).md +++ b/problems/0714.买卖股票的最佳时机含手续费(动态规划).md @@ -226,7 +226,7 @@ func max(a, b int) int { } ``` -### Javascript: +### JavaScript: ```javascript const maxProfit = (prices,fee) => { diff --git a/problems/0738.单调递增的数字.md b/problems/0738.单调递增的数字.md index 3d46d5ad..8de22fe2 100644 --- a/problems/0738.单调递增的数字.md +++ b/problems/0738.单调递增的数字.md @@ -292,7 +292,7 @@ func monotoneIncreasingDigits(N int) int { } ``` -### Javascript +### JavaScript ```Javascript var monotoneIncreasingDigits = function(n) { n = n.toString() diff --git a/problems/0763.划分字母区间.md b/problems/0763.划分字母区间.md index 52186927..19d862db 100644 --- a/problems/0763.划分字母区间.md +++ b/problems/0763.划分字母区间.md @@ -312,7 +312,7 @@ func max(a, b int) int { } ``` -### Javascript +### JavaScript ```Javascript var partitionLabels = function(s) { let hash = {} diff --git a/problems/0860.柠檬水找零.md b/problems/0860.柠檬水找零.md index 804ff13c..b7887d45 100644 --- a/problems/0860.柠檬水找零.md +++ b/problems/0860.柠檬水找零.md @@ -226,7 +226,7 @@ func lemonadeChange(bills []int) bool { } ``` -### Javascript +### JavaScript ```Javascript var lemonadeChange = function(bills) { let fiveCount = 0 diff --git a/problems/0968.监控二叉树.md b/problems/0968.监控二叉树.md index d59496c8..327c54f7 100644 --- a/problems/0968.监控二叉树.md +++ b/problems/0968.监控二叉树.md @@ -536,7 +536,7 @@ func min(a, b int) int { ``` -### Javascript +### JavaScript ```Javascript var minCameraCover = function(root) { diff --git a/problems/0977.有序数组的平方.md b/problems/0977.有序数组的平方.md index effa9055..3f16951d 100644 --- a/problems/0977.有序数组的平方.md +++ b/problems/0977.有序数组的平方.md @@ -263,7 +263,7 @@ impl Solution { } } ``` -### Javascript: +### JavaScript: ```Javascript /** @@ -289,7 +289,7 @@ var sortedSquares = function(nums) { }; ``` -### Typescript: +### TypeScript: 双指针法: diff --git a/problems/1005.K次取反后最大化的数组和.md b/problems/1005.K次取反后最大化的数组和.md index 4e049600..1a781777 100644 --- a/problems/1005.K次取反后最大化的数组和.md +++ b/problems/1005.K次取反后最大化的数组和.md @@ -207,7 +207,7 @@ func largestSumAfterKNegations(nums []int, K int) int { ``` -### Javascript +### JavaScript ```Javascript var largestSumAfterKNegations = function(nums, k) { diff --git a/problems/1971.寻找图中是否存在路径.md b/problems/1971.寻找图中是否存在路径.md index 2c5901ae..93e9b663 100644 --- a/problems/1971.寻找图中是否存在路径.md +++ b/problems/1971.寻找图中是否存在路径.md @@ -213,7 +213,7 @@ class Solution: return find(source) == find(destination) ``` -### Javascript: +### JavaScript: Javascript 并查集解法如下: diff --git a/problems/kamacoder/0047.参会dijkstra堆.md b/problems/kamacoder/0047.参会dijkstra堆.md index 9905a420..75c12f8a 100644 --- a/problems/kamacoder/0047.参会dijkstra堆.md +++ b/problems/kamacoder/0047.参会dijkstra堆.md @@ -911,7 +911,7 @@ func main() { ### Rust -### Javascript +### JavaScript ### TypeScript diff --git a/problems/kamacoder/0047.参会dijkstra朴素.md b/problems/kamacoder/0047.参会dijkstra朴素.md index 465ad16d..e794690a 100644 --- a/problems/kamacoder/0047.参会dijkstra朴素.md +++ b/problems/kamacoder/0047.参会dijkstra朴素.md @@ -867,7 +867,7 @@ if __name__ == "__main__": ### Rust -### Javascript +### JavaScript ```js function dijkstra(grid, start, end) { diff --git a/problems/kamacoder/0053.寻宝-Kruskal.md b/problems/kamacoder/0053.寻宝-Kruskal.md index 6a227985..861efe68 100644 --- a/problems/kamacoder/0053.寻宝-Kruskal.md +++ b/problems/kamacoder/0053.寻宝-Kruskal.md @@ -547,7 +547,7 @@ if __name__ == "__main__": ### Rust -### Javascript +### JavaScript ```js function kruskal(v, edges) { diff --git a/problems/kamacoder/0053.寻宝-prim.md b/problems/kamacoder/0053.寻宝-prim.md index a8dad4cb..bbcea026 100644 --- a/problems/kamacoder/0053.寻宝-prim.md +++ b/problems/kamacoder/0053.寻宝-prim.md @@ -692,7 +692,7 @@ if __name__ == "__main__": ### Rust -### Javascript +### JavaScript ```js function prim(v, edges) { const grid = Array.from({ length: v + 1 }, () => new Array(v + 1).fill(10001)); // Fixed grid initialization diff --git a/problems/kamacoder/0094.城市间货物运输I-SPFA.md b/problems/kamacoder/0094.城市间货物运输I-SPFA.md index b3f42bf8..6881f072 100644 --- a/problems/kamacoder/0094.城市间货物运输I-SPFA.md +++ b/problems/kamacoder/0094.城市间货物运输I-SPFA.md @@ -462,7 +462,7 @@ if __name__ == "__main__": ### Rust -### Javascript +### JavaScript ### TypeScript diff --git a/problems/kamacoder/0094.城市间货物运输I.md b/problems/kamacoder/0094.城市间货物运输I.md index 3737fe01..b20d25ef 100644 --- a/problems/kamacoder/0094.城市间货物运输I.md +++ b/problems/kamacoder/0094.城市间货物运输I.md @@ -483,7 +483,7 @@ if __name__ == "__main__": ### Rust -### Javascript +### JavaScript ### TypeScript diff --git a/problems/kamacoder/0095.城市间货物运输II.md b/problems/kamacoder/0095.城市间货物运输II.md index edfd52e0..3a306689 100644 --- a/problems/kamacoder/0095.城市间货物运输II.md +++ b/problems/kamacoder/0095.城市间货物运输II.md @@ -392,7 +392,7 @@ if __name__ == "__main__": ### Rust -### Javascript +### JavaScript ### TypeScript diff --git a/problems/kamacoder/0096.城市间货物运输III.md b/problems/kamacoder/0096.城市间货物运输III.md index dacd23d1..8e815263 100644 --- a/problems/kamacoder/0096.城市间货物运输III.md +++ b/problems/kamacoder/0096.城市间货物运输III.md @@ -708,7 +708,7 @@ public class Main { ### Rust -### Javascript +### JavaScript ### TypeScript diff --git a/problems/kamacoder/0097.小明逛公园.md b/problems/kamacoder/0097.小明逛公园.md index e8d92cc2..8b3078fc 100644 --- a/problems/kamacoder/0097.小明逛公园.md +++ b/problems/kamacoder/0097.小明逛公园.md @@ -492,7 +492,7 @@ if __name__ == '__main__': ### Rust -### Javascript +### JavaScript ### TypeScript diff --git a/problems/kamacoder/0098.所有可达路径.md b/problems/kamacoder/0098.所有可达路径.md index db35524f..734435f9 100644 --- a/problems/kamacoder/0098.所有可达路径.md +++ b/problems/kamacoder/0098.所有可达路径.md @@ -726,7 +726,7 @@ func main() { ### Rust -### Javascript +### JavaScript #### 邻接矩阵写法 diff --git a/problems/kamacoder/0099.岛屿的数量广搜.md b/problems/kamacoder/0099.岛屿的数量广搜.md index 30475753..68b475a0 100644 --- a/problems/kamacoder/0099.岛屿的数量广搜.md +++ b/problems/kamacoder/0099.岛屿的数量广搜.md @@ -360,7 +360,7 @@ func main() { ### Rust -### Javascript +### JavaScript ```javascript const r1 = require('readline').createInterface({ input: process.stdin }); diff --git a/problems/kamacoder/0099.岛屿的数量深搜.md b/problems/kamacoder/0099.岛屿的数量深搜.md index 6ac7ba3b..33d0c9dc 100644 --- a/problems/kamacoder/0099.岛屿的数量深搜.md +++ b/problems/kamacoder/0099.岛屿的数量深搜.md @@ -328,7 +328,7 @@ if __name__ == '__main__': ### Rust -### Javascript +### JavaScript ```javascript const r1 = require('readline').createInterface({ input: process.stdin }); diff --git a/problems/kamacoder/0100.岛屿的最大面积.md b/problems/kamacoder/0100.岛屿的最大面积.md index 51bfc57f..a3e2a99e 100644 --- a/problems/kamacoder/0100.岛屿的最大面积.md +++ b/problems/kamacoder/0100.岛屿的最大面积.md @@ -390,7 +390,7 @@ func main() { ### Rust -### Javascript +### JavaScript ```javascript // 广搜版 diff --git a/problems/kamacoder/0101.孤岛的总面积.md b/problems/kamacoder/0101.孤岛的总面积.md index 26c92c07..af5ce089 100644 --- a/problems/kamacoder/0101.孤岛的总面积.md +++ b/problems/kamacoder/0101.孤岛的总面积.md @@ -467,7 +467,7 @@ func main() { ### Rust -### Javascript +### JavaScript #### 深搜版 diff --git a/problems/kamacoder/0102.沉没孤岛.md b/problems/kamacoder/0102.沉没孤岛.md index 4eabc516..a7e28df5 100644 --- a/problems/kamacoder/0102.沉没孤岛.md +++ b/problems/kamacoder/0102.沉没孤岛.md @@ -322,7 +322,7 @@ for row in g: ### Rust -### Javascript +### JavaScript #### 深搜版 diff --git a/problems/kamacoder/0103.水流问题.md b/problems/kamacoder/0103.水流问题.md index 9a34bf09..a09bf089 100644 --- a/problems/kamacoder/0103.水流问题.md +++ b/problems/kamacoder/0103.水流问题.md @@ -416,7 +416,7 @@ if __name__ == "__main__": ### Rust -### Javascript +### JavaScript #### 深搜 diff --git a/problems/kamacoder/0104.建造最大岛屿.md b/problems/kamacoder/0104.建造最大岛屿.md index 3dcbfee6..ffb6cae3 100644 --- a/problems/kamacoder/0104.建造最大岛屿.md +++ b/problems/kamacoder/0104.建造最大岛屿.md @@ -530,7 +530,7 @@ if __name__ == "__main__": ### Rust -### Javascript +### JavaScript ```javascript const r1 = require('readline').createInterface({ input: process.stdin }); diff --git a/problems/kamacoder/0105.有向图的完全可达性.md b/problems/kamacoder/0105.有向图的完全可达性.md index 838b0212..3bfcfb40 100644 --- a/problems/kamacoder/0105.有向图的完全可达性.md +++ b/problems/kamacoder/0105.有向图的完全可达性.md @@ -489,7 +489,7 @@ func main() { ### Rust -### Javascript +### JavaScript ### TypeScript diff --git a/problems/kamacoder/0106.岛屿的周长.md b/problems/kamacoder/0106.岛屿的周长.md index 235d9445..91a1a438 100644 --- a/problems/kamacoder/0106.岛屿的周长.md +++ b/problems/kamacoder/0106.岛屿的周长.md @@ -343,7 +343,7 @@ func parseLine(line string, count int) []int { ### Rust -### Javascript +### JavaScript ### TypeScript diff --git a/problems/kamacoder/0107.寻找存在的路径.md b/problems/kamacoder/0107.寻找存在的路径.md index 09ad0d5e..779907c8 100644 --- a/problems/kamacoder/0107.寻找存在的路径.md +++ b/problems/kamacoder/0107.寻找存在的路径.md @@ -340,7 +340,7 @@ func main() { ### Rust -### Javascript +### JavaScript ```java const r1 = require('readline').createInterface({ input: process.stdin }); diff --git a/problems/kamacoder/0108.冗余连接.md b/problems/kamacoder/0108.冗余连接.md index 18a86ad6..efbbb6d2 100644 --- a/problems/kamacoder/0108.冗余连接.md +++ b/problems/kamacoder/0108.冗余连接.md @@ -221,7 +221,7 @@ if __name__ == "__main__": ### Rust -### Javascript +### JavaScript ```javascript const r1 = require('readline').createInterface({ input: process.stdin }); diff --git a/problems/kamacoder/0109.冗余连接II.md b/problems/kamacoder/0109.冗余连接II.md index 2bd4eac6..4365c27f 100644 --- a/problems/kamacoder/0109.冗余连接II.md +++ b/problems/kamacoder/0109.冗余连接II.md @@ -441,7 +441,7 @@ if __name__ == "__main__": ### Rust -### Javascript +### JavaScript ```javascript const r1 = require('readline').createInterface({ input: process.stdin }); diff --git a/problems/kamacoder/0110.字符串接龙.md b/problems/kamacoder/0110.字符串接龙.md index 308e50b7..6541faba 100644 --- a/problems/kamacoder/0110.字符串接龙.md +++ b/problems/kamacoder/0110.字符串接龙.md @@ -254,7 +254,7 @@ if __name__=='__main__': ### Rust -### Javascript +### JavaScript ```javascript const r1 = require('readline').createInterface({ input: process.stdin }); diff --git a/problems/kamacoder/0117.软件构建.md b/problems/kamacoder/0117.软件构建.md index 348187d6..58c17763 100644 --- a/problems/kamacoder/0117.软件构建.md +++ b/problems/kamacoder/0117.软件构建.md @@ -449,7 +449,7 @@ if __name__ == "__main__": ### Rust -### Javascript +### JavaScript ```javascript const r1 = require('readline').createInterface({ input: process.stdin }); diff --git a/problems/kamacoder/0126.骑士的攻击astar.md b/problems/kamacoder/0126.骑士的攻击astar.md index 2d0481ec..80fc033b 100644 --- a/problems/kamacoder/0126.骑士的攻击astar.md +++ b/problems/kamacoder/0126.骑士的攻击astar.md @@ -373,7 +373,7 @@ for _ in range(n): ### Rust -### Javascript +### JavaScript ### TypeScript diff --git a/problems/二叉树的递归遍历.md b/problems/二叉树的递归遍历.md index f2a97f4d..8f61b8c6 100644 --- a/problems/二叉树的递归遍历.md +++ b/problems/二叉树的递归遍历.md @@ -283,7 +283,7 @@ func postorderTraversal(root *TreeNode) (res []int) { } ``` -### Javascript: +### JavaScript: 前序遍历: ```Javascript diff --git a/problems/背包理论基础01背包-1.md b/problems/背包理论基础01背包-1.md index 2747f179..e7ad8d1d 100644 --- a/problems/背包理论基础01背包-1.md +++ b/problems/背包理论基础01背包-1.md @@ -492,7 +492,7 @@ func max(x, y int) int { ``` -### Javascript +### JavaScript ```js const readline = require('readline').createInterface({ diff --git a/problems/背包问题理论基础完全背包.md b/problems/背包问题理论基础完全背包.md index 3a50ee7b..ae1e9e0b 100644 --- a/problems/背包问题理论基础完全背包.md +++ b/problems/背包问题理论基础完全背包.md @@ -392,7 +392,7 @@ func main() { fmt.Println(test_CompletePack2(weight, price, 4)) } ``` -### Javascript: +### JavaScript: ```Javascript // 先遍历物品,再遍历背包容量 From 7683e173384162dd8a95b2a5412b56a230a2f858 Mon Sep 17 00:00:00 2001 From: markwang Date: Thu, 17 Oct 2024 13:28:39 +0800 Subject: [PATCH 31/65] =?UTF-8?q?1143.=E6=9C=80=E9=95=BF=E5=85=AC=E5=85=B1?= =?UTF-8?q?=E5=AD=90=E5=BA=8F=E5=88=97=E6=96=87=E5=AD=97=E5=8B=98=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/1143.最长公共子序列.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/problems/1143.最长公共子序列.md b/problems/1143.最长公共子序列.md index 25f32838..6d05ccf3 100644 --- a/problems/1143.最长公共子序列.md +++ b/problems/1143.最长公共子序列.md @@ -80,7 +80,7 @@ if (text1[i - 1] == text2[j - 1]) { 先看看dp[i][0]应该是多少呢? -test1[0, i-1]和空串的最长公共子序列自然是0,所以dp[i][0] = 0; +text1[0, i-1]和空串的最长公共子序列自然是0,所以dp[i][0] = 0; 同理dp[0][j]也是0。 From 09fef9f8f8172418eaeeab631a6d10e774080a12 Mon Sep 17 00:00:00 2001 From: markwang Date: Thu, 17 Oct 2024 15:58:28 +0800 Subject: [PATCH 32/65] =?UTF-8?q?1035.=E4=B8=8D=E7=9B=B8=E4=BA=A4=E7=9A=84?= =?UTF-8?q?=E7=BA=BF=E9=A2=98=E7=9B=AE=E6=8F=8F=E8=BF=B0=E5=8F=8A=E5=8F=82?= =?UTF-8?q?=E6=95=B0=E5=90=8D=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/1035.不相交的线.md | 56 +++++++++++++++++--------------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/problems/1035.不相交的线.md b/problems/1035.不相交的线.md index 8ee52c5d..5164e1f7 100644 --- a/problems/1035.不相交的线.md +++ b/problems/1035.不相交的线.md @@ -8,11 +8,16 @@ [力扣题目链接](https://leetcode.cn/problems/uncrossed-lines/) -我们在两条独立的水平线上按给定的顺序写下 A 和 B 中的整数。 +在两条独立的水平线上按给定的顺序写下 nums1 和 nums2 中的整数。 -现在,我们可以绘制一些连接两个数字 A[i] 和 B[j] 的直线,只要 A[i] == B[j],且我们绘制的直线不与任何其他连线(非水平线)相交。 +现在,可以绘制一些连接两个数字 nums1[i] 和 nums2[j] 的直线,这些直线需要同时满足: -以这种方法绘制线条,并返回我们可以绘制的最大连线数。 +* nums1[i] == nums2[j] +* 且绘制的直线不与任何其他连线(非水平线)相交。 + +请注意,连线即使在端点也不能相交:每个数字只能属于一条连线。 + +以这种方法绘制线条,并返回可以绘制的最大连线数。 ![1035.不相交的线](https://code-thinking-1253855093.file.myqcloud.com/pics/2021032116363533.png) @@ -26,16 +31,16 @@ 相信不少录友看到这道题目都没啥思路,我们来逐步分析一下。 -绘制一些连接两个数字 A[i] 和 B[j] 的直线,只要 A[i] == B[j],且直线不能相交! +绘制一些连接两个数字 nums1[i] 和 nums2[j] 的直线,只要 nums1[i] == nums2[j],且直线不能相交! -直线不能相交,这就是说明在字符串A中 找到一个与字符串B相同的子序列,且这个子序列不能改变相对顺序,只要相对顺序不改变,链接相同数字的直线就不会相交。 +直线不能相交,这就是说明在字符串nums1中 找到一个与字符串nums2相同的子序列,且这个子序列不能改变相对顺序,只要相对顺序不改变,连接相同数字的直线就不会相交。 -拿示例一A = [1,4,2], B = [1,2,4]为例,相交情况如图: +拿示例一nums1 = [1,4,2], nums2 = [1,2,4]为例,相交情况如图: ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20210914145158.png) -其实也就是说A和B的最长公共子序列是[1,4],长度为2。 这个公共子序列指的是相对顺序不变(即数字4在字符串A中数字1的后面,那么数字4也应该在字符串B数字1的后面) +其实也就是说nums1和nums2的最长公共子序列是[1,4],长度为2。 这个公共子序列指的是相对顺序不变(即数字4在字符串nums1中数字1的后面,那么数字4也应该在字符串nums2数字1的后面) 这么分析完之后,大家可以发现:**本题说是求绘制的最大连线数,其实就是求两个字符串的最长公共子序列的长度!** @@ -52,18 +57,18 @@ ```CPP class Solution { public: - int maxUncrossedLines(vector& A, vector& B) { - vector> dp(A.size() + 1, vector(B.size() + 1, 0)); - for (int i = 1; i <= A.size(); i++) { - for (int j = 1; j <= B.size(); j++) { - if (A[i - 1] == B[j - 1]) { + int maxUncrossedLines(vector& nums1, vector& nums2) { + vector> dp(nums1.size() + 1, vector(nums2.size() + 1, 0)); + for (int i = 1; i <= nums1.size(); i++) { + for (int j = 1; j <= nums2.size(); j++) { + if (nums1[i - 1] == nums2[j - 1]) { dp[i][j] = dp[i - 1][j - 1] + 1; } else { dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]); } } } - return dp[A.size()][B.size()]; + return dp[nums1.size()][nums2.size()]; } }; ``` @@ -110,11 +115,11 @@ public: ```python class Solution: - def maxUncrossedLines(self, A: List[int], B: List[int]) -> int: - dp = [[0] * (len(B)+1) for _ in range(len(A)+1)] - for i in range(1, len(A)+1): - for j in range(1, len(B)+1): - if A[i-1] == B[j-1]: + def maxUncrossedLines(self, nums1: List[int], nums2: List[int]) -> int: + dp = [[0] * (len(nums2)+1) for _ in range(len(nums1)+1)] + for i in range(1, len(nums1)+1): + for j in range(1, len(nums2)+1): + if nums1[i-1] == nums2[j-1]: dp[i][j] = dp[i-1][j-1] + 1 else: dp[i][j] = max(dp[i-1][j], dp[i][j-1]) @@ -124,23 +129,22 @@ class Solution: ### Go: ```go -func maxUncrossedLines(A []int, B []int) int { - m, n := len(A), len(B) - dp := make([][]int, m+1) +func maxUncrossedLines(nums1 []int, nums2 []int) int { + dp := make([][]int, len(nums1) + 1) for i := range dp { - dp[i] = make([]int, n+1) + dp[i] = make([]int, len(nums2) + 1) } - for i := 1; i <= len(A); i++ { - for j := 1; j <= len(B); j++ { - if (A[i - 1] == B[j - 1]) { + for i := 1; i <= len(nums1); i++ { + for j := 1; j <= len(nums2); j++ { + if (nums1[i - 1] == nums2[j - 1]) { dp[i][j] = dp[i - 1][j - 1] + 1 } else { dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) } } } - return dp[m][n] + return dp[len(nums1)][len(nums2)] } From 048ec95f07174e991fb0309200d5d14334957238 Mon Sep 17 00:00:00 2001 From: Lane Zhang Date: Mon, 21 Oct 2024 13:10:23 +0800 Subject: [PATCH 33/65] =?UTF-8?q?0232.=E7=94=A8=E6=A0=88=E5=AE=9E=E7=8E=B0?= =?UTF-8?q?=E9=98=9F=E5=88=97.md=20=E6=97=B6=E9=97=B4=E5=A4=8D=E6=9D=82?= =?UTF-8?q?=E5=BA=A6=E5=BA=94=E4=B8=BAO(1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0232.用栈实现队列.md | 2 +- problems/双指针总结.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/problems/0232.用栈实现队列.md b/problems/0232.用栈实现队列.md index 7017107b..657567cf 100644 --- a/problems/0232.用栈实现队列.md +++ b/problems/0232.用栈实现队列.md @@ -113,7 +113,7 @@ public: ``` -* 时间复杂度: push和empty为O(1), pop和peek为O(n) +* 时间复杂度: 都为O(1)。pop和peek看起来像O(n),实际上一个循环n会被使用n次,最后还是O(1)。 * 空间复杂度: O(n) diff --git a/problems/双指针总结.md b/problems/双指针总结.md index a77490cd..409e80ab 100644 --- a/problems/双指针总结.md +++ b/problems/双指针总结.md @@ -77,7 +77,7 @@ for (int i = 0; i < array.size(); i++) { 时间复杂度可以做到O(n^2),但还是比较费时的,因为不好做剪枝操作。 -所以这道题目使用双指针法才是最为合适的,用双指针做这道题目才能就能真正体会到,**通过前后两个指针不算向中间逼近,在一个for循环下完成两个for循环的工作。** +所以这道题目使用双指针法才是最为合适的,用双指针做这道题目才能就能真正体会到,**通过前后两个指针不断向中间逼近,在一个for循环下完成两个for循环的工作。** 只用双指针法时间复杂度为O(n^2),但比哈希法的O(n^2)效率高得多,哈希法在使用两层for循环的时候,能做的剪枝操作很有限。 From e0c1e2e31784dfb13ea8f710ff216bcdccf5d3bf Mon Sep 17 00:00:00 2001 From: zhangrunzhe Date: Mon, 21 Oct 2024 19:02:33 +0800 Subject: [PATCH 34/65] =?UTF-8?q?=E9=9D=A2=E8=AF=95=E9=A2=9802.07.?= =?UTF-8?q?=E9=93=BE=E8=A1=A8=E7=9B=B8=E4=BA=A4=20Swift=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/面试题02.07.链表相交.md | 39 +++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/problems/面试题02.07.链表相交.md b/problems/面试题02.07.链表相交.md index b0f2e8ea..48944b5e 100644 --- a/problems/面试题02.07.链表相交.md +++ b/problems/面试题02.07.链表相交.md @@ -535,6 +535,45 @@ public ListNode GetIntersectionNode(ListNode headA, ListNode headB) } ``` +### Swift: +```swift +func getIntersectionNode(_ headA: ListNode?, _ headB: ListNode?) -> ListNode? { + var lenA = 0 + var lenB = 0 + var nodeA = headA + var nodeB = headB + // 计算链表A和链表B的长度 + while nodeA != nil { + lenA += 1 + nodeA = nodeA?.next + } + while nodeB != nil { + lenB += 1 + nodeB = nodeB?.next + } + // 重置指针 + nodeA = headA + nodeB = headB + // 如果链表A更长,让它先走lenA-lenB步 + if lenA > lenB { + for _ in 0..<(lenA - lenB) { + nodeA = nodeA?.next + } + } else if lenB > lenA { + // 如果链表B更长,让它先走lenB-lenA步 + for _ in 0..<(lenB - lenA) { + nodeB = nodeB?.next + } + } + // 同时遍历两个链表,寻找交点 + while nodeA !== nodeB { + nodeA = nodeA?.next + nodeB = nodeB?.next + } + return nodeA +} +``` +

From fba159b1356bf4fe55658c05090b1b3ae7956e10 Mon Sep 17 00:00:00 2001 From: Lane Zhang Date: Tue, 22 Oct 2024 09:20:21 +0800 Subject: [PATCH 35/65] =?UTF-8?q?0239.=E6=BB=91=E5=8A=A8=E7=AA=97=E5=8F=A3?= =?UTF-8?q?=E6=9C=80=E5=A4=A7=E5=80=BC.md=20=E5=8A=A0=E5=85=A5=20Python=20?= =?UTF-8?q?=E7=89=88=E6=9C=AC=E8=A7=A3=E6=B3=95=E4=BA=8C=EF=BC=9A=E7=9B=B4?= =?UTF-8?q?=E6=8E=A5=E7=94=A8=E5=8D=95=E8=B0=83=E9=98=9F=E5=88=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0239.滑动窗口最大值.md | 32 +++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/problems/0239.滑动窗口最大值.md b/problems/0239.滑动窗口最大值.md index 23bf615b..aae1b4d2 100644 --- a/problems/0239.滑动窗口最大值.md +++ b/problems/0239.滑动窗口最大值.md @@ -299,7 +299,7 @@ class Solution { ``` ### Python: - +#### 解法一:使用自定义的单调队列类 ```python from collections import deque @@ -339,6 +339,36 @@ class Solution: return result ``` +#### 解法二:直接用单调队列 +```python +from collections import deque + + +class Solution: + def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]: + max_list = [] # 结果集合 + kept_nums = deque() # 单调队列 + + for i in range(len(nums)): + update_kept_nums(kept_nums, nums[i]) # 右侧新元素加入 + + if i >= k and nums[i - k] == kept_nums[0]: # 左侧旧元素如果等于单调队列头元素,需要移除头元素 + kept_nums.popleft() + + if i >= k - 1: + max_list.append(kept_nums[0]) + + return max_list + + +def update_kept_nums(kept_nums, num): # num 是新加入的元素 + # 所有小于新元素的队列尾部元素,在新元素出现后,都是没有价值的,都需要被移除 + while kept_nums and num > kept_nums[-1]: + kept_nums.pop() + + kept_nums.append(num) +``` + ### Go: ```go From e5ebc38dddeb6a356f892d7e3d930f9f257790b1 Mon Sep 17 00:00:00 2001 From: Kristy-an Date: Mon, 21 Oct 2024 21:12:06 -0500 Subject: [PATCH 36/65] fix python block code highlight problem --- problems/0503.下一个更大元素II.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/problems/0503.下一个更大元素II.md b/problems/0503.下一个更大元素II.md index 5751bb91..056b7096 100644 --- a/problems/0503.下一个更大元素II.md +++ b/problems/0503.下一个更大元素II.md @@ -185,7 +185,7 @@ class Solution: > 版本二:针对版本一的优化 -```python3 +```python class Solution: def nextGreaterElements(self, nums: List[int]) -> List[int]: res = [-1] * len(nums) From 97c4d1baec4789f7fe8aa656b459fc63509548a7 Mon Sep 17 00:00:00 2001 From: Lane Zhang Date: Tue, 22 Oct 2024 10:22:27 +0800 Subject: [PATCH 37/65] =?UTF-8?q?0239.=E6=BB=91=E5=8A=A8=E7=AA=97=E5=8F=A3?= =?UTF-8?q?=E6=9C=80=E5=A4=A7=E5=80=BC.md=20=E5=8A=A0=E5=85=A5=20Python=20?= =?UTF-8?q?=E7=89=88=E6=9C=AC=E6=96=B0=E8=A7=A3=E6=B3=95=EF=BC=9A=E7=94=A8?= =?UTF-8?q?"=E5=A0=86=E6=8E=92=E5=BA=8F"=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0239.滑动窗口最大值.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/problems/0239.滑动窗口最大值.md b/problems/0239.滑动窗口最大值.md index 23bf615b..2db1942a 100644 --- a/problems/0239.滑动窗口最大值.md +++ b/problems/0239.滑动窗口最大值.md @@ -339,6 +339,32 @@ class Solution: return result ``` +#### 新解法:用"堆排序"实现 +* 时间复杂度:`O(n * log(n))`, 比`单调队列`解法要慢。 + +```python +import heapq + + +class Solution: + def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]: + results = [] + num_index_list = [] # 将用“堆排序”对它进行排序,元素为 (num, index) 元组 + + for i in range(len(nums)): + # 把 nums[i] 值取负数,最大的就到最小,合乎 Python 堆排序从小到大的规则。 + # 还要把 index (i) 存入,因为通过 i 可知道对应的 num 何时不能再被使用(num 已经处在左侧窗口的更左边) + heapq.heappush(num_index_list, (-nums[i], i)) + # num_index_list[0]是最小值所在 tuple;'<= i - k' 表示 num 已经处在左侧窗口的更左边 + while num_index_list[0][1] <= i - k: # while 表示所有过气 num 都要丢弃 + heapq.heappop(num_index_list) # 丢弃最小值 + + if i >= k - 1: + results.append(-num_index_list[0][0]) # 第一个就是最小值,负最小值就是最大值,加入结果集 + + return results +``` + ### Go: ```go From ad93277357f14ab7a7436c8ee92c74e65fb37fd3 Mon Sep 17 00:00:00 2001 From: Kuxry Date: Tue, 22 Oct 2024 11:46:28 +0900 Subject: [PATCH 38/65] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20203.=E7=A7=BB?= =?UTF-8?q?=E9=99=A4=E9=93=BE=E8=A1=A8=E5=85=83=E7=B4=A0=20Ruby=20?= =?UTF-8?q?=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0203.移除链表元素.md | 38 +++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/problems/0203.移除链表元素.md b/problems/0203.移除链表元素.md index f6b5ef6d..c2f1d449 100644 --- a/problems/0203.移除链表元素.md +++ b/problems/0203.移除链表元素.md @@ -737,7 +737,45 @@ public class Solution } } ``` +### Ruby# +```ruby +# 定义链表节点 +class ListNode + attr_accessor :val, :next + def initialize(val = 0, _next = nil) + @val = val + @next = _next + end +end + +# 删除链表中值为 val 的节点 +def remove_elements(head, val) + # 创建一个虚拟头节点,这样可以简化删除头节点的处理 + # 虚拟头节点的值为 0,指向当前链表的头节点 + dummy = ListNode.new(0) + dummy.next = head + + # 初始化当前节点为虚拟头节点 + current = dummy + + # 遍历链表,直到当前节点的下一个节点为空 + while current.next + # 如果当前节点的下一个节点的值等于 val + if current.next.val == val + # 跳过该节点,即将当前节点的 next 指向下一个节点的 next + current.next = current.next.next + else + # 否则继续遍历,当前节点向前移动 + current = current.next + end + end + + # 返回删除 val 后的新链表的头节点,虚拟头节点的 next 就是新的头节点 + dummy.next +end + +```

From 6e6093752fb67bbcd9d67211013c1d6ac740e0b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lane=20Zhang=20=28=E5=BC=A0=E5=81=A5=29?= Date: Tue, 22 Oct 2024 11:00:13 +0800 Subject: [PATCH 39/65] =?UTF-8?q?Update=200239.=E6=BB=91=E5=8A=A8=E7=AA=97?= =?UTF-8?q?=E5=8F=A3=E6=9C=80=E5=A4=A7=E5=80=BC.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change `O(n * log(n))` to `O(n log(n))` --- problems/0239.滑动窗口最大值.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/problems/0239.滑动窗口最大值.md b/problems/0239.滑动窗口最大值.md index 2db1942a..95c38acb 100644 --- a/problems/0239.滑动窗口最大值.md +++ b/problems/0239.滑动窗口最大值.md @@ -340,7 +340,7 @@ class Solution: ``` #### 新解法:用"堆排序"实现 -* 时间复杂度:`O(n * log(n))`, 比`单调队列`解法要慢。 +* 时间复杂度:`O(n log(n))`, 比`单调队列`解法要慢。 ```python import heapq From 6eb35a973796c440fde91ae5ef66fe75c1dfb426 Mon Sep 17 00:00:00 2001 From: markwang Date: Wed, 23 Oct 2024 16:19:36 +0800 Subject: [PATCH 40/65] =?UTF-8?q?503.=E4=B8=8B=E4=B8=80=E4=B8=AA=E6=9B=B4?= =?UTF-8?q?=E5=A4=A7=E5=85=83=E7=B4=A0II=E5=A2=9E=E5=8A=A0Go=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E4=B8=80=E8=A7=A3=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0503.下一个更大元素II.md | 34 ++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/problems/0503.下一个更大元素II.md b/problems/0503.下一个更大元素II.md index 5751bb91..fdbdc1cf 100644 --- a/problems/0503.下一个更大元素II.md +++ b/problems/0503.下一个更大元素II.md @@ -213,6 +213,40 @@ class Solution: ### Go: ```go +// 版本一 +func nextGreaterElements(nums []int) []int { + // 拼接一个新的nums + numsNew := make([]int, len(nums) * 2) + copy(numsNew, nums) + copy(numsNew[len(nums):], nums) + // 用新的nums大小来初始化result + result := make([]int, len(numsNew)) + for i := range result { + result[i] = -1 + } + + // 开始单调栈 + st := []int{0} + for i := 1; i < len(numsNew); i++ { + if numsNew[i] < numsNew[st[len(st)-1]] { + st = append(st, i) + } else if numsNew[i] == numsNew[st[len(st)-1]] { + st = append(st, i) + } else { + for len(st) > 0 && numsNew[i] > numsNew[st[len(st)-1]] { + result[st[len(st)-1]] = numsNew[i] + st = st[:len(st)-1] + } + st = append(st, i) + } + } + result = result[:len(result)/2] + return result +} +``` + +```go +// 版本二 func nextGreaterElements(nums []int) []int { length := len(nums) result := make([]int,length) From 46bb8d64082111260b0f5e8042443ce257c95d9c Mon Sep 17 00:00:00 2001 From: Leehouc <152672308+Leehouc@users.noreply.github.com> Date: Wed, 23 Oct 2024 20:26:42 +0800 Subject: [PATCH 41/65] =?UTF-8?q?=E9=94=99=E5=AD=97=200669.=E4=BF=AE?= =?UTF-8?q?=E5=89=AA=E4=BA=8C=E5=8F=89=E6=90=9C=E7=B4=A2=E6=A0=91.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0669.修剪二叉搜索树.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/problems/0669.修剪二叉搜索树.md b/problems/0669.修剪二叉搜索树.md index aef84659..32573386 100644 --- a/problems/0669.修剪二叉搜索树.md +++ b/problems/0669.修剪二叉搜索树.md @@ -22,7 +22,7 @@ ## 算法公开课 -**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[你修剪的方式不对,我来给你纠正一下!| LeetCode:669. 修剪二叉搜索树](https://www.bilibili.com/video/BV17P41177ud?share_source=copy_web),相信结合视频在看本篇题解,更有助于大家对本题的理解**。 +**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[你修剪的方式不对,我来给你纠正一下!| LeetCode:669. 修剪二叉搜索树](https://www.bilibili.com/video/BV17P41177ud?share_source=copy_web),相信结合视频再看本篇题解,更有助于大家对本题的理解**。 ## 思路 From 83565ed41768333098fe78694f9990b280f64879 Mon Sep 17 00:00:00 2001 From: Leehouc <152672308+Leehouc@users.noreply.github.com> Date: Wed, 23 Oct 2024 20:28:57 +0800 Subject: [PATCH 42/65] =?UTF-8?q?=E9=94=99=E5=AD=970450.=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E4=BA=8C=E5=8F=89=E6=90=9C=E7=B4=A2=E6=A0=91=E4=B8=AD=E7=9A=84?= =?UTF-8?q?=E8=8A=82=E7=82=B9.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0450.删除二叉搜索树中的节点.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/problems/0450.删除二叉搜索树中的节点.md b/problems/0450.删除二叉搜索树中的节点.md index f6057f44..cab9880a 100644 --- a/problems/0450.删除二叉搜索树中的节点.md +++ b/problems/0450.删除二叉搜索树中的节点.md @@ -26,7 +26,7 @@ ## 算法公开课 -**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[调整二叉树的结构最难!| LeetCode:450.删除二叉搜索树中的节点](https://www.bilibili.com/video/BV1tP41177us?share_source=copy_web),相信结合视频在看本篇题解,更有助于大家对本题的理解**。 +**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[调整二叉树的结构最难!| LeetCode:450.删除二叉搜索树中的节点](https://www.bilibili.com/video/BV1tP41177us?share_source=copy_web),相信结合视频再看本篇题解,更有助于大家对本题的理解**。 ## 思路 From 0c674bb9179b06aa055fb0c10d3432f985b12f28 Mon Sep 17 00:00:00 2001 From: Leehouc <152672308+Leehouc@users.noreply.github.com> Date: Wed, 23 Oct 2024 20:31:04 +0800 Subject: [PATCH 43/65] =?UTF-8?q?Update=200235.=E4=BA=8C=E5=8F=89=E6=90=9C?= =?UTF-8?q?=E7=B4=A2=E6=A0=91=E7=9A=84=E6=9C=80=E8=BF=91=E5=85=AC=E5=85=B1?= =?UTF-8?q?=E7=A5=96=E5=85=88.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0235.二叉搜索树的最近公共祖先.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/problems/0235.二叉搜索树的最近公共祖先.md b/problems/0235.二叉搜索树的最近公共祖先.md index 597c2dff..192bb031 100644 --- a/problems/0235.二叉搜索树的最近公共祖先.md +++ b/problems/0235.二叉搜索树的最近公共祖先.md @@ -38,7 +38,7 @@ ## 算法公开课 -**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[二叉搜索树找祖先就有点不一样了!| 235. 二叉搜索树的最近公共祖先](https://www.bilibili.com/video/BV1Zt4y1F7ww?share_source=copy_web),相信结合视频在看本篇题解,更有助于大家对本题的理解**。 +**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[二叉搜索树找祖先就有点不一样了!| 235. 二叉搜索树的最近公共祖先](https://www.bilibili.com/video/BV1Zt4y1F7ww?share_source=copy_web),相信结合视频再看本篇题解,更有助于大家对本题的理解**。 ## 思路 From 041ac6bbdc0da8d557702d2fac7c51f6b1e7c8c4 Mon Sep 17 00:00:00 2001 From: Leehouc <152672308+Leehouc@users.noreply.github.com> Date: Wed, 23 Oct 2024 20:31:48 +0800 Subject: [PATCH 44/65] =?UTF-8?q?Update=200530.=E4=BA=8C=E5=8F=89=E6=90=9C?= =?UTF-8?q?=E7=B4=A2=E6=A0=91=E7=9A=84=E6=9C=80=E5=B0=8F=E7=BB=9D=E5=AF=B9?= =?UTF-8?q?=E5=B7=AE.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0530.二叉搜索树的最小绝对差.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/problems/0530.二叉搜索树的最小绝对差.md b/problems/0530.二叉搜索树的最小绝对差.md index 7fe64ad2..2533a618 100644 --- a/problems/0530.二叉搜索树的最小绝对差.md +++ b/problems/0530.二叉搜索树的最小绝对差.md @@ -21,7 +21,7 @@ ## 算法公开课 -**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[二叉搜索树中,需要掌握如何双指针遍历!| LeetCode:530.二叉搜索树的最小绝对差](https://www.bilibili.com/video/BV1DD4y11779),相信结合视频在看本篇题解,更有助于大家对本题的理解**。 +**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[二叉搜索树中,需要掌握如何双指针遍历!| LeetCode:530.二叉搜索树的最小绝对差](https://www.bilibili.com/video/BV1DD4y11779),相信结合视频再看本篇题解,更有助于大家对本题的理解**。 ## 思路 From 12236fa616878d49799cd0d6606d8a7f0d026ff8 Mon Sep 17 00:00:00 2001 From: Leehouc <152672308+Leehouc@users.noreply.github.com> Date: Wed, 23 Oct 2024 20:32:25 +0800 Subject: [PATCH 45/65] =?UTF-8?q?Update=200098.=E9=AA=8C=E8=AF=81=E4=BA=8C?= =?UTF-8?q?=E5=8F=89=E6=90=9C=E7=B4=A2=E6=A0=91.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0098.验证二叉搜索树.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/problems/0098.验证二叉搜索树.md b/problems/0098.验证二叉搜索树.md index 023eeea5..fb4ca7d8 100644 --- a/problems/0098.验证二叉搜索树.md +++ b/problems/0098.验证二叉搜索树.md @@ -22,7 +22,7 @@ ## 算法公开课 -**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[你对二叉搜索树了解的还不够! | LeetCode:98.验证二叉搜索树](https://www.bilibili.com/video/BV18P411n7Q4),相信结合视频在看本篇题解,更有助于大家对本题的理解**。 +**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[你对二叉搜索树了解的还不够! | LeetCode:98.验证二叉搜索树](https://www.bilibili.com/video/BV18P411n7Q4),相信结合视频再看本篇题解,更有助于大家对本题的理解**。 ## 思路 From 779c16ca104556d442ddf23501026528495eb3a5 Mon Sep 17 00:00:00 2001 From: Leehouc <152672308+Leehouc@users.noreply.github.com> Date: Wed, 23 Oct 2024 20:32:53 +0800 Subject: [PATCH 46/65] =?UTF-8?q?Update=200501.=E4=BA=8C=E5=8F=89=E6=90=9C?= =?UTF-8?q?=E7=B4=A2=E6=A0=91=E4=B8=AD=E7=9A=84=E4=BC=97=E6=95=B0.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0501.二叉搜索树中的众数.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/problems/0501.二叉搜索树中的众数.md b/problems/0501.二叉搜索树中的众数.md index 93b3fb54..c89f8031 100644 --- a/problems/0501.二叉搜索树中的众数.md +++ b/problems/0501.二叉搜索树中的众数.md @@ -35,7 +35,7 @@ ## 算法公开课 -**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[不仅双指针,还有代码技巧可以惊艳到你! | LeetCode:501.二叉搜索树中的众数](https://www.bilibili.com/video/BV1fD4y117gp),相信结合视频在看本篇题解,更有助于大家对本题的理解**。 +**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[不仅双指针,还有代码技巧可以惊艳到你! | LeetCode:501.二叉搜索树中的众数](https://www.bilibili.com/video/BV1fD4y117gp),相信结合视频再看本篇题解,更有助于大家对本题的理解**。 ## 思路 From 2d62182265b9825f0eed8a451f1119558867db46 Mon Sep 17 00:00:00 2001 From: Leehouc <152672308+Leehouc@users.noreply.github.com> Date: Wed, 23 Oct 2024 20:35:56 +0800 Subject: [PATCH 47/65] =?UTF-8?q?Update=200236.=E4=BA=8C=E5=8F=89=E6=A0=91?= =?UTF-8?q?=E7=9A=84=E6=9C=80=E8=BF=91=E5=85=AC=E5=85=B1=E7=A5=96=E5=85=88?= =?UTF-8?q?.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0236.二叉树的最近公共祖先.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/problems/0236.二叉树的最近公共祖先.md b/problems/0236.二叉树的最近公共祖先.md index 2e94f7a7..8572ec2d 100644 --- a/problems/0236.二叉树的最近公共祖先.md +++ b/problems/0236.二叉树的最近公共祖先.md @@ -36,7 +36,7 @@ ## 算法公开课 -**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[自底向上查找,有点难度! | LeetCode:236. 二叉树的最近公共祖先](https://www.bilibili.com/video/BV1jd4y1B7E2),相信结合视频在看本篇题解,更有助于大家对本题的理解**。 +**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html):[自底向上查找,有点难度! | LeetCode:236. 二叉树的最近公共祖先](https://www.bilibili.com/video/BV1jd4y1B7E2),相信结合视频再看本篇题解,更有助于大家对本题的理解**。 ## 思路 From 2ddf04ff1432c5a3f0fdf81061913a5c7fcccd47 Mon Sep 17 00:00:00 2001 From: zhangrunzhe Date: Thu, 24 Oct 2024 18:04:48 +0800 Subject: [PATCH 48/65] =?UTF-8?q?=E5=8F=B3=E6=97=8B=E5=AD=97=E7=AC=A6?= =?UTF-8?q?=E4=B8=B2=20swift=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/kamacoder/0055.右旋字符串.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/problems/kamacoder/0055.右旋字符串.md b/problems/kamacoder/0055.右旋字符串.md index 363d9ffa..2b32cb44 100644 --- a/problems/kamacoder/0055.右旋字符串.md +++ b/problems/kamacoder/0055.右旋字符串.md @@ -350,7 +350,29 @@ function reverseStr(s, start, end) { ### Swift: +```swift +func rotateWords(_ s: String, _ k: Int) -> String { + var chars = Array(s) + // 先反转整体 + reverseWords(&chars, start: 0, end: s.count - 1) + // 反转前半段 + reverseWords(&chars, start: 0, end: k - 1) + // 反转后半段 + reverseWords(&chars, start: k, end: s.count - 1) + return String(chars) +} +// 反转start...end 的字符数组 +func reverseWords(_ chars: inout [Character], start: Int, end: Int) { + var left = start + var right = end + while left < right, right < chars.count { + (chars[left], chars[right]) = (chars[right], chars[left]) + left += 1 + right -= 1 + } +} +``` ### PHP: From d64a5359383d7d1fe399b33f2319f7253cd131f7 Mon Sep 17 00:00:00 2001 From: HONGYAN ZHAO Date: Thu, 24 Oct 2024 21:07:17 -0500 Subject: [PATCH 49/65] Debug python version, change strip() to split() --- problems/kamacoder/0101.孤岛的总面积.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/problems/kamacoder/0101.孤岛的总面积.md b/problems/kamacoder/0101.孤岛的总面积.md index 26c92c07..408501ff 100644 --- a/problems/kamacoder/0101.孤岛的总面积.md +++ b/problems/kamacoder/0101.孤岛的总面积.md @@ -261,10 +261,10 @@ public class Main { from collections import deque # 处理输入 -n, m = list(map(int, input().strip())) +n, m = list(map(int, input().split())) g = [] for _ in range(n): - row = list(map(int, input().strip())) + row = list(map(int, input().split())) g.append(row) # 定义四个方向、孤岛面积(遍历完边缘后会被重置) From 492f45f53d6e46bfed1d91cc91fe0a3d91964ead Mon Sep 17 00:00:00 2001 From: HONGYAN ZHAO Date: Thu, 24 Oct 2024 21:08:52 -0500 Subject: [PATCH 50/65] debug python version, set visited[x][y] to True in the beginning of bfs --- problems/kamacoder/0099.岛屿的数量广搜.md | 1 + 1 file changed, 1 insertion(+) diff --git a/problems/kamacoder/0099.岛屿的数量广搜.md b/problems/kamacoder/0099.岛屿的数量广搜.md index 9d31c922..522e19c3 100644 --- a/problems/kamacoder/0099.岛屿的数量广搜.md +++ b/problems/kamacoder/0099.岛屿的数量广搜.md @@ -254,6 +254,7 @@ directions = [[0, 1], [1, 0], [0, -1], [-1, 0]] def bfs(grid, visited, x, y): que = deque([]) que.append([x,y]) + visited[x][y] = True while que: cur_x, cur_y = que.popleft() for i, j in directions: From b9a060f195f704a09b7acf50e3ff36cb090471d0 Mon Sep 17 00:00:00 2001 From: Captainzw <80784797+Captain-zhangw@users.noreply.github.com> Date: Sat, 26 Oct 2024 20:16:14 +0800 Subject: [PATCH 51/65] =?UTF-8?q?=E4=BF=AE=E6=94=B9=20README.md=E4=B8=AD?= =?UTF-8?q?=20=E2=80=9Cbellman=5Fford=E4=B9=8B=E5=8D=95=E6=BA=90=E6=9C=89?= =?UTF-8?q?=E9=99=90=E6=9C=80=E7=9F=AD=E8=B7=AF=E2=80=9D=E7=9A=84=E9=94=99?= =?UTF-8?q?=E8=AF=AF=E9=93=BE=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3bb575d1..d1f4f3a8 100644 --- a/README.md +++ b/README.md @@ -400,7 +400,7 @@ 24. [图论:Bellman_ford 算法](./problems/kamacoder/0094.城市间货物运输I.md) 25. [图论:Bellman_ford 队列优化算法(又名SPFA)](./problems/kamacoder/0094.城市间货物运输I-SPFA.md) 26. [图论:Bellman_ford之判断负权回路](./problems/kamacoder/0095.城市间货物运输II.md) -27. [图论:Bellman_ford之单源有限最短路](./problems/kamacoder/0095.城市间货物运输II.md) +27. [图论:Bellman_ford之单源有限最短路](./problems/kamacoder/0096.城市间货物运输III.md) 28. [图论:Floyd 算法](./problems/kamacoder/0097.小明逛公园.md) 29. [图论:A * 算法](./problems/kamacoder/0126.骑士的攻击astar.md) 30. [图论:最短路算法总结篇](./problems/kamacoder/最短路问题总结篇.md) From 74909977cd13549da4368f09b550da2474f1c807 Mon Sep 17 00:00:00 2001 From: Captainzw <80784797+Captain-zhangw@users.noreply.github.com> Date: Sat, 26 Oct 2024 20:31:53 +0800 Subject: [PATCH 52/65] =?UTF-8?q?=E4=BF=AE=E6=94=B9=200096.=E5=9F=8E?= =?UTF-8?q?=E5=B8=82=E9=97=B4=E8=B4=A7=E7=89=A9=E8=BF=90=E8=BE=93III.md=20?= =?UTF-8?q?=E4=B8=AD=E7=9A=84=E9=94=99=E8=AF=AF=E9=93=BE=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kamacoder/0096.城市间货物运输III.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/problems/kamacoder/0096.城市间货物运输III.md b/problems/kamacoder/0096.城市间货物运输III.md index 567a1d87..1facf7b2 100644 --- a/problems/kamacoder/0096.城市间货物运输III.md +++ b/problems/kamacoder/0096.城市间货物运输III.md @@ -51,15 +51,15 @@ ## 思路 -本题为单源有限最短路问题,同样是 [kama94.城市间货物运输I](./kama94.城市间货物运输I.md) 延伸题目。 +本题为单源有限最短路问题,同样是 [kama94.城市间货物运输I](./0094.城市间货物运输I.md) 延伸题目。 注意题目中描述是 **最多经过 k 个城市的条件下,而不是一定经过k个城市,也可以经过的城市数量比k小,但要最短的路径**。 -在 [kama94.城市间货物运输I](./kama94.城市间货物运输I.md) 中我们讲了:**对所有边松弛一次,相当于计算 起点到达 与起点一条边相连的节点 的最短距离**。 +在 [kama94.城市间货物运输I](./0094.城市间货物运输I.md) 中我们讲了:**对所有边松弛一次,相当于计算 起点到达 与起点一条边相连的节点 的最短距离**。 节点数量为n,起点到终点,最多是 n-1 条边相连。 那么对所有边松弛 n-1 次 就一定能得到 起点到达 终点的最短距离。 -(如果对以上讲解看不懂,建议详看 [kama94.城市间货物运输I](./kama94.城市间货物运输I.md) ) +(如果对以上讲解看不懂,建议详看 [kama94.城市间货物运输I](./0094.城市间货物运输I.md) ) 本题是最多经过 k 个城市, 那么是 k + 1条边相连的节点。 这里可能有录友想不懂为什么是k + 1,来看这个图: @@ -71,7 +71,7 @@ 对所有边松弛一次,相当于计算 起点到达 与起点一条边相连的节点 的最短距离,那么对所有边松弛 k + 1次,就是求 起点到达 与起点k + 1条边相连的节点的 最短距离。 -**注意**: 本题是 [kama94.城市间货物运输I](./kama94.城市间货物运输I.md) 的拓展题,如果对 bellman_ford 没有深入了解,强烈建议先看 [kama94.城市间货物运输I](./kama94.城市间货物运输I.md) 再做本题。 +**注意**: 本题是 [kama94.城市间货物运输I](./0094.城市间货物运输I.md) 的拓展题,如果对 bellman_ford 没有深入了解,强烈建议先看 [kama94.城市间货物运输I](./0094.城市间货物运输I.md) 再做本题。 理解以上内容,其实本题代码就很容易了,bellman_ford 标准写法是松弛 n-1 次,本题就松弛 k + 1次就好。 @@ -366,19 +366,19 @@ int main() { ## 拓展二(本题本质) -那么前面讲解过的 [94.城市间货物运输I](./kama94.城市间货物运输I.md) 和 [95.城市间货物运输II](./kama95.城市间货物运输II.md) 也是bellman_ford经典算法,也没使用 minDist_copy,怎么就没问题呢? +那么前面讲解过的 [94.城市间货物运输I](./0094.城市间货物运输I.md) 和 [95.城市间货物运输II](./0095.城市间货物运输II.md) 也是bellman_ford经典算法,也没使用 minDist_copy,怎么就没问题呢? > 如果没看过我上面这两篇讲解的话,建议详细学习上面两篇,再看我下面讲的区别,否则容易看不懂。 -[94.城市间货物运输I](./kama94.城市间货物运输I.md), 是没有 负权回路的,那么 多松弛多少次,对结果都没有影响。 +[94.城市间货物运输I](./0094.城市间货物运输I.md), 是没有 负权回路的,那么 多松弛多少次,对结果都没有影响。 求 节点1 到 节点n 的最短路径,松弛n-1 次就够了,松弛 大于 n-1次,结果也不会变。 那么在对所有边进行第一次松弛的时候,如果基于 本次计算的 minDist 来计算 minDist (相当于多做松弛了),也是对最终结果没影响。 -[95.城市间货物运输II](./kama95.城市间货物运输II.md) 是判断是否有 负权回路,一旦有负权回路, 对所有边松弛 n-1 次以后,在做松弛 minDist 数值一定会变,根据这一点来判断是否有负权回路。 +[95.城市间货物运输II](./0095.城市间货物运输II.md) 是判断是否有 负权回路,一旦有负权回路, 对所有边松弛 n-1 次以后,在做松弛 minDist 数值一定会变,根据这一点来判断是否有负权回路。 -所以,[95.城市间货物运输II](./kama95.城市间货物运输II.md) 只需要判断minDist数值变化了就行,而 minDist 的数值对不对,并不是我们关心的。 +所以,[95.城市间货物运输II](./0095.城市间货物运输II.md) 只需要判断minDist数值变化了就行,而 minDist 的数值对不对,并不是我们关心的。 那么本题 为什么计算minDist 一定要基于上次 的 minDist 数值。 From 7cb657dc508465362d74b6133bd060c42eddf610 Mon Sep 17 00:00:00 2001 From: Captainzw <80784797+Captain-zhangw@users.noreply.github.com> Date: Sat, 26 Oct 2024 20:33:16 +0800 Subject: [PATCH 53/65] =?UTF-8?q?=E4=BF=AE=E6=94=B9=200095.=E5=9F=8E?= =?UTF-8?q?=E5=B8=82=E9=97=B4=E8=B4=A7=E7=89=A9=E8=BF=90=E8=BE=93II.md=20?= =?UTF-8?q?=E4=B8=AD=E7=9A=84=E9=94=99=E8=AF=AF=E9=93=BE=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/kamacoder/0095.城市间货物运输II.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/problems/kamacoder/0095.城市间货物运输II.md b/problems/kamacoder/0095.城市间货物运输II.md index edfd52e0..ac6ccf3c 100644 --- a/problems/kamacoder/0095.城市间货物运输II.md +++ b/problems/kamacoder/0095.城市间货物运输II.md @@ -54,7 +54,7 @@ circle ## 思路 -本题是 [kama94.城市间货物运输I](./kama94.城市间货物运输I.md) 延伸题目。 +本题是 [kama94.城市间货物运输I](./0094.城市间货物运输I.md) 延伸题目。 本题是要我们判断 负权回路,也就是图中出现环且环上的边总权值为负数。 @@ -64,7 +64,7 @@ circle 接下来我们来看 如何使用 bellman_ford 算法来判断 负权回路。 -在 [kama94.城市间货物运输I](./kama94.城市间货物运输I.md) 中 我们讲了 bellman_ford 算法的核心就是一句话:对 所有边 进行 n-1 次松弛。 同时文中的 【拓展】部分, 我们也讲了 松弛n次以上 会怎么样? +在 [kama94.城市间货物运输I](./0094.城市间货物运输I.md) 中 我们讲了 bellman_ford 算法的核心就是一句话:对 所有边 进行 n-1 次松弛。 同时文中的 【拓展】部分, 我们也讲了 松弛n次以上 会怎么样? 在没有负权回路的图中,松弛 n 次以上 ,结果不会有变化。 @@ -72,7 +72,7 @@ circle 那么每松弛一次,都会更新最短路径,所以结果会一直有变化。 -(如果对于 bellman_ford 不了解的录友,建议详细看这里:[kama94.城市间货物运输I](./kama94.城市间货物运输I.md)) +(如果对于 bellman_ford 不了解的录友,建议详细看这里:[kama94.城市间货物运输I](./0094.城市间货物运输I.md)) 以上为理论分析,接下来我们再画图举例。 @@ -94,13 +94,13 @@ circle 如果在负权回路多绕两圈,三圈,无穷圈,那么我们的总成本就会无限小, 如果要求最小成本的话,你会发现本题就无解了。 -在 bellman_ford 算法中,松弛 n-1 次所有的边 就可以求得 起点到任何节点的最短路径,松弛 n 次以上,minDist数组(记录起到到其他节点的最短距离)中的结果也不会有改变 (如果对 bellman_ford 算法 不了解,也不知道 minDist 是什么,建议详看上篇讲解[kama94.城市间货物运输I](./kama94.城市间货物运输I.md)) +在 bellman_ford 算法中,松弛 n-1 次所有的边 就可以求得 起点到任何节点的最短路径,松弛 n 次以上,minDist数组(记录起到到其他节点的最短距离)中的结果也不会有改变 (如果对 bellman_ford 算法 不了解,也不知道 minDist 是什么,建议详看上篇讲解[kama94.城市间货物运输I](./0094.城市间货物运输I.md)) 而本题有负权回路的情况下,一直都会有更短的最短路,所以 松弛 第n次,minDist数组 也会发生改变。 -那么解决本题的 核心思路,就是在 [kama94.城市间货物运输I](./kama94.城市间货物运输I.md) 的基础上,再多松弛一次,看minDist数组 是否发生变化。 +那么解决本题的 核心思路,就是在 [kama94.城市间货物运输I](./0094.城市间货物运输I.md) 的基础上,再多松弛一次,看minDist数组 是否发生变化。 -代码和 [kama94.城市间货物运输I](./kama94.城市间货物运输I.md) 基本是一样的,如下:(关键地方已注释) +代码和 [kama94.城市间货物运输I](./0094.城市间货物运输I.md) 基本是一样的,如下:(关键地方已注释) ```CPP #include From 28de17ec3921f86376f493a781727e7589d26b73 Mon Sep 17 00:00:00 2001 From: Kuxry Date: Wed, 30 Oct 2024 09:54:39 +0900 Subject: [PATCH 54/65] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=200126.=E9=AA=91?= =?UTF-8?q?=E5=A3=AB=E7=9A=84=E6=94=BB=E5=87=BBastar=20C=E8=AF=AD=E8=A8=80?= =?UTF-8?q?=20=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kamacoder/0126.骑士的攻击astar.md | 165 +++++++++++++++++- 1 file changed, 164 insertions(+), 1 deletion(-) diff --git a/problems/kamacoder/0126.骑士的攻击astar.md b/problems/kamacoder/0126.骑士的攻击astar.md index 2d0481ec..403fe1fa 100644 --- a/problems/kamacoder/0126.骑士的攻击astar.md +++ b/problems/kamacoder/0126.骑士的攻击astar.md @@ -389,7 +389,170 @@ for _ in range(n): ### C - +```C +#include +#include +#include + +// 定义一个结构体,表示棋盘上骑士的位置和相关的 A* 算法参数 +typedef struct { + int x, y; // 骑士在棋盘上的坐标 + int g; // 从起点到当前节点的实际消耗 + int h; // 从当前节点到目标节点的估计消耗(启发式函数值) + int f; // 总的估计消耗(f = g + h) +} Knight; + +#define MAX_HEAP_SIZE 2000000 // 优先队列的最大容量 + +// 定义一个优先队列,使用最小堆来实现 A* 算法中的 Open 列表 +typedef struct { + Knight data[MAX_HEAP_SIZE]; + int size; +} PriorityQueue; + +// 初始化优先队列 +void initQueue(PriorityQueue *pq) { + pq->size = 0; +} + +// 将骑士节点插入优先队列 +void push(PriorityQueue *pq, Knight k) { + if (pq->size >= MAX_HEAP_SIZE) { + // 堆已满,无法插入新节点 + return; + } + int i = pq->size++; + pq->data[i] = k; + // 上滤操作,维护最小堆的性质,使得 f 值最小的节点在堆顶 + while (i > 0) { + int parent = (i - 1) / 2; + if (pq->data[parent].f <= pq->data[i].f) { + break; + } + // 交换父节点和当前节点 + Knight temp = pq->data[parent]; + pq->data[parent] = pq->data[i]; + pq->data[i] = temp; + i = parent; + } +} + +// 从优先队列中弹出 f 值最小的骑士节点 +Knight pop(PriorityQueue *pq) { + Knight min = pq->data[0]; + pq->size--; + pq->data[0] = pq->data[pq->size]; + // 下滤操作,维护最小堆的性质 + int i = 0; + while (1) { + int left = 2 * i + 1; + int right = 2 * i + 2; + int smallest = i; + if (left < pq->size && pq->data[left].f < pq->data[smallest].f) { + smallest = left; + } + if (right < pq->size && pq->data[right].f < pq->data[smallest].f) { + smallest = right; + } + if (smallest == i) { + break; + } + // 交换当前节点与最小子节点 + Knight temp = pq->data[smallest]; + pq->data[smallest] = pq->data[i]; + pq->data[i] = temp; + i = smallest; + } + return min; +} + +// 判断优先队列是否为空 +int isEmpty(PriorityQueue *pq) { + return pq->size == 0; +} + +// 启发式函数:计算从当前位置到目标位置的欧几里得距离的平方(避免开方,提高效率) +int heuristic(int x, int y, int goal_x, int goal_y) { + int dx = x - goal_x; + int dy = y - goal_y; + return dx * dx + dy * dy; // 欧几里得距离的平方 +} + +// 用于记录从起点到棋盘上每个位置的最小移动次数 +int moves[1001][1001]; + +// 骑士在棋盘上的8个可能移动方向 +int dir[8][2] = { + {-2, -1}, {-2, 1}, {-1, 2}, {1, 2}, + {2, 1}, {2, -1}, {1, -2}, {-1, -2} +}; + +// 使用 A* 算法寻找从起点到目标点的最短路径 +int astar(int start_x, int start_y, int goal_x, int goal_y) { + PriorityQueue pq; + initQueue(&pq); + + // 初始化 moves 数组,-1 表示未访问过的位置 + memset(moves, -1, sizeof(moves)); + moves[start_x][start_y] = 0; // 起点位置的移动次数为 0 + + // 初始化起始节点 + Knight start; + start.x = start_x; + start.y = start_y; + start.g = 0; // 从起点到起点的消耗为 0 + start.h = heuristic(start_x, start_y, goal_x, goal_y); + start.f = start.g + start.h; // 总的估计消耗 + + push(&pq, start); // 将起始节点加入优先队列 + + while (!isEmpty(&pq)) { + Knight current = pop(&pq); // 取出 f 值最小的节点 + + // 如果已经到达目标位置,返回所需的最小移动次数 + if (current.x == goal_x && current.y == goal_y) { + return moves[current.x][current.y]; + } + + // 遍历当前节点的所有可能移动方向 + for (int i = 0; i < 8; i++) { + int nx = current.x + dir[i][0]; + int ny = current.y + dir[i][1]; + + // 检查新位置是否在棋盘范围内且未被访问过 + if (nx >= 1 && nx <= 1000 && ny >= 1 && ny <= 1000 && moves[nx][ny] == -1) { + moves[nx][ny] = moves[current.x][current.y] + 1; // 更新移动次数 + + // 创建新节点,表示骑士移动到的新位置 + Knight neighbor; + neighbor.x = nx; + neighbor.y = ny; + neighbor.g = current.g + 5; // 每次移动的消耗为 5(骑士移动的距离平方) + neighbor.h = heuristic(nx, ny, goal_x, goal_y); + neighbor.f = neighbor.g + neighbor.h; + + push(&pq, neighbor); // 将新节点加入优先队列 + } + } + } + + return -1; // 如果无法到达目标位置,返回 -1 +} + +int main() { + int n; + scanf("%d", &n); + while (n--) { + int a1, a2, b1, b2; // 起点和目标点的坐标 + scanf("%d %d %d %d", &a1, &a2, &b1, &b2); + + int result = astar(a1, a2, b1, b2); // 使用 A* 算法计算最短路径 + printf("%d\n", result); // 输出所需的最小移动次数 + } + return 0; +} + +``` From ef36f40e4365cff7113c0f084d9cc3058de6e469 Mon Sep 17 00:00:00 2001 From: Kuxry Date: Wed, 30 Oct 2024 10:34:03 +0900 Subject: [PATCH 55/65] =?UTF-8?q?=20=E6=B7=BB=E5=8A=A00126.=E9=AA=91?= =?UTF-8?q?=E5=A3=AB=E7=9A=84=E6=94=BB=E5=87=BBastar=20C=E8=AF=AD=E8=A8=80?= =?UTF-8?q?=20=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/kamacoder/0126.骑士的攻击astar.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/problems/kamacoder/0126.骑士的攻击astar.md b/problems/kamacoder/0126.骑士的攻击astar.md index 403fe1fa..e3ce98f6 100644 --- a/problems/kamacoder/0126.骑士的攻击astar.md +++ b/problems/kamacoder/0126.骑士的攻击astar.md @@ -500,7 +500,7 @@ int astar(int start_x, int start_y, int goal_x, int goal_y) { Knight start; start.x = start_x; start.y = start_y; - start.g = 0; // 从起点到起点的消耗为 0 + start.g = 0; start.h = heuristic(start_x, start_y, goal_x, goal_y); start.f = start.g + start.h; // 总的估计消耗 @@ -547,7 +547,7 @@ int main() { scanf("%d %d %d %d", &a1, &a2, &b1, &b2); int result = astar(a1, a2, b1, b2); // 使用 A* 算法计算最短路径 - printf("%d\n", result); // 输出所需的最小移动次数 + printf("%d\n", result); // 输出最小移动次数 } return 0; } From 2602359ec9a62a08987234d95c7e3cc2571894ad Mon Sep 17 00:00:00 2001 From: Kuxry Date: Wed, 30 Oct 2024 10:48:07 +0900 Subject: [PATCH 56/65] =?UTF-8?q?=20=E6=B7=BB=E5=8A=A00126.=E9=AA=91?= =?UTF-8?q?=E5=A3=AB=E7=9A=84=E6=94=BB=E5=87=BBastar=20C=E8=AF=AD=E8=A8=80?= =?UTF-8?q?=20=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/kamacoder/0126.骑士的攻击astar.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/problems/kamacoder/0126.骑士的攻击astar.md b/problems/kamacoder/0126.骑士的攻击astar.md index e3ce98f6..3bbf4169 100644 --- a/problems/kamacoder/0126.骑士的攻击astar.md +++ b/problems/kamacoder/0126.骑士的攻击astar.md @@ -402,7 +402,7 @@ typedef struct { int f; // 总的估计消耗(f = g + h) } Knight; -#define MAX_HEAP_SIZE 2000000 // 优先队列的最大容量 +#define MAX_HEAP_SIZE 2000000 // 假设优先队列的最大容量 // 定义一个优先队列,使用最小堆来实现 A* 算法中的 Open 列表 typedef struct { From 85241be1ea8a07b6449b2ef24d4abfacf4211bc1 Mon Sep 17 00:00:00 2001 From: DengSchoo <46556279+DengSchoo@users.noreply.github.com> Date: Tue, 5 Nov 2024 17:41:16 +0800 Subject: [PATCH 57/65] chore: create .gitignore file create a .gitignore file to avoid uploading useless files, such as ".DS_Store". --- .gitignore | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..4bd29f75 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +.idea/ +.DS_Store +.vscode +.temp +.cache +*.iml +__pycache__ From 55e8b33e1d9f9236b939d2be7a0160eecfb2beb8 Mon Sep 17 00:00:00 2001 From: DengSchoo <46556279+DengSchoo@users.noreply.github.com> Date: Tue, 5 Nov 2024 17:42:16 +0800 Subject: [PATCH 58/65] chore: remove useless file ".DS_Store" --- .DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index f7ce0fd5038358c7a0df77b968ed993daff0639c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKF-`+P3>-s>lW0;>?icvMDhe;i2T%y2IdUiw)YtKC#$F>OS}4*`z*zFmt?k*> zO>sU0u+`h{4p;&h=#KdCr8m#JcXpK#M~gE?JmCe$-SKhks=p67cfczSn6SkOe>+Vh z5ABoho5Oyb_Rq|DUM2;kfE17dQa}n^q(HXM;pQTiilu-Q_zw#B_o2`oYvSB6J{??Q z1RyRL4&!so62#&GVojVIGD5RPB{r(%h+&P+c*(k&I5%u`SlrBW@@C5k#o~6xOO(TE zL#5>MJ5G)LxE2gD;uo< From 9e6cc0e627c20a28c8928e76cb8cde342a5e0b25 Mon Sep 17 00:00:00 2001 From: swjtuhjf Date: Thu, 7 Nov 2024 23:44:18 +0800 Subject: [PATCH 59/65] =?UTF-8?q?0053.=E5=AF=BB=E5=AE=9D-prim=201.=20?= =?UTF-8?q?=E5=88=A0=E6=8E=89=E6=96=87=E7=AB=A0=E4=B8=AD=E5=86=97=E4=BD=99?= =?UTF-8?q?=E7=9A=84=E7=A9=BA=E6=A0=BC=EF=BC=8C=E4=BD=86=E4=B8=8D=E5=8C=85?= =?UTF-8?q?=E6=8B=AC1=E4=BB=A3=E7=A0=81=E4=B8=AD=E7=9A=84=E7=A9=BA?= =?UTF-8?q?=E6=A0=BC=E5=92=8C2=E7=BB=93=E6=9E=84=E6=80=A7=E7=A9=BA?= =?UTF-8?q?=E6=A0=BC(=E5=A6=82=E6=A0=87=E9=A2=98=E5=86=85)=E7=AD=89?= =?UTF-8?q?=E5=90=88=E7=90=86=E7=A9=BA=E6=A0=BC=202.=20=E5=B0=86=E6=80=BB?= =?UTF-8?q?=E7=BB=93=E9=83=A8=E5=88=86=E5=80=92=E6=95=B0=E7=AC=AC=E4=B8=89?= =?UTF-8?q?=E5=8F=A5=E4=B8=AD"=E5=A6=82=E4=BD=95=E6=B1=82=E8=81=8C?= =?UTF-8?q?=E6=9C=80=E5=B0=8F=E7=94=9F=E6=88=90=E6=A0=91=E7=9A=84=E6=AF=8F?= =?UTF-8?q?=E4=B8=80=E6=9D=A1=E8=BE=B9"=E7=9A=84"=E6=B1=82=E8=81=8C"?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=B8=BA"=E8=8E=B7=E5=BE=97"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/kamacoder/0053.寻宝-prim.md | 280 ++++++++++++------------- 1 file changed, 140 insertions(+), 140 deletions(-) diff --git a/problems/kamacoder/0053.寻宝-prim.md b/problems/kamacoder/0053.寻宝-prim.md index a8dad4cb..d2c9578a 100644 --- a/problems/kamacoder/0053.寻宝-prim.md +++ b/problems/kamacoder/0053.寻宝-prim.md @@ -9,17 +9,17 @@ 在世界的某个区域,有一些分散的神秘岛屿,每个岛屿上都有一种珍稀的资源或者宝藏。国王打算在这些岛屿上建公路,方便运输。 -不同岛屿之间,路途距离不同,国王希望你可以规划建公路的方案,如何可以以最短的总公路距离将 所有岛屿联通起来。 +不同岛屿之间,路途距离不同,国王希望你可以规划建公路的方案,如何可以以最短的总公路距离将所有岛屿联通起来。 给定一张地图,其中包括了所有的岛屿,以及它们之间的距离。以最小化公路建设长度,确保可以链接到所有岛屿。 输入描述: -第一行包含两个整数V 和 E,V代表顶点数,E代表边数 。顶点编号是从1到V。例如:V=2,一个有两个顶点,分别是1和2。 +第一行包含两个整数V和E,V代表顶点数,E代表边数。顶点编号是从1到V。例如:V=2,一个有两个顶点,分别是1和2。 -接下来共有 E 行,每行三个整数 v1,v2 和 val,v1 和 v2 为边的起点和终点,val代表边的权值。 +接下来共有E行,每行三个整数v1,v2和val,v1和v2为边的起点和终点,val代表边的权值。 -输出描述: +输出描述: 输出联通所有岛屿的最小路径总距离 @@ -38,65 +38,65 @@ 5 6 2 5 7 1 6 7 1 -``` +``` -输出示例: +输出示例: 6 -## 解题思路 +## 解题思路 -本题是最小生成树的模板题,那么我们来讲一讲最小生成树。 +本题是最小生成树的模板题,那么我们来讲一讲最小生成树。 -最小生成树 可以使用 prim算法 也可以使用 kruskal算法计算出来。 +最小生成树可以使用prim算法也可以使用kruskal算法计算出来。 -本篇我们先讲解 prim算法。 +本篇我们先讲解prim算法。 -最小生成树是所有节点的最小连通子图, 即:以最小的成本(边的权值)将图中所有节点链接到一起。 +最小生成树是所有节点的最小连通子图,即:以最小的成本(边的权值)将图中所有节点链接到一起。 -图中有n个节点,那么一定可以用 n - 1 条边将所有节点连接到一起。 +图中有n个节点,那么一定可以用n-1条边将所有节点连接到一起。 -那么如何选择 这 n-1 条边 就是 最小生成树算法的任务所在。 +那么如何选择这n-1条边就是最小生成树算法的任务所在。 -例如本题示例中的无向有权图为: +例如本题示例中的无向有权图为: ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20231206164306.png) -那么在这个图中,如何选取 n-1 条边 使得 图中所有节点连接到一起,并且边的权值和最小呢? +那么在这个图中,如何选取n-1条边使得图中所有节点连接到一起,并且边的权值和最小呢? -(图中为n为7,即7个节点,那么只需要 n-1 即 6条边就可以讲所有顶点连接到一起) +(图中为n为7,即7个节点,那么只需要n-1即6条边就可以讲所有顶点连接到一起) -prim算法 是从节点的角度 采用贪心的策略 每次寻找距离 最小生成树最近的节点 并加入到最小生成树中。 +prim算法是从节点的角度采用贪心的策略每次寻找距离最小生成树最近的节点并加入到最小生成树中。 -prim算法核心就是三步,我称为**prim三部曲**,大家一定要熟悉这三步,代码相对会好些很多: +prim算法核心就是三步,我称为**prim三部曲**,大家一定要熟悉这三步,代码相对会好些很多: 1. 第一步,选距离生成树最近节点 -2. 第二步,最近节点加入生成树 +2. 第二步,最近节点加入生成树 3. 第三步,更新非生成树节点到生成树的距离(即更新minDist数组) -现在录友们会对这三步很陌生,不知道这是干啥的,没关系,下面将会画图举例来带大家把这**prim三部曲**理解到位。 +现在录友们会对这三步很陌生,不知道这是干啥的,没关系,下面将会画图举例来带大家把这**prim三部曲**理解到位。 在prim算法中,有一个数组特别重要,这里我起名为:minDist。 -刚刚我有讲过 “每次寻找距离 最小生成树最近的节点 并加入到最小生成树中”,那么如何寻找距离最小生成树最近的节点呢? +刚刚我有讲过“每次寻找距离最小生成树最近的节点并加入到最小生成树中”,那么如何寻找距离最小生成树最近的节点呢? -这就用到了 minDist 数组, 它用来作什么呢? +这就用到了minDist数组,它用来作什么呢? -**minDist数组 用来记录 每一个节点距离最小生成树的最近距离**。 理解这一点非常重要,这也是 prim算法最核心要点所在,很多录友看不懂prim算法的代码,都是因为没有理解透 这个数组的含义。 +**minDist数组用来记录每一个节点距离最小生成树的最近距离**。理解这一点非常重要,这也是prim算法最核心要点所在,很多录友看不懂prim算法的代码,都是因为没有理解透这个数组的含义。 -接下来,我们来通过一步一步画图,来带大家巩固 **prim三部曲** 以及 minDist数组 的作用。 +接下来,我们来通过一步一步画图,来带大家巩固**prim三部曲**以及minDist数组的作用。 -(**示例中节点编号是从1开始,所以为了让大家看的不晕,minDist数组下标我也从 1 开始计数,下标0 就不使用了,这样 下标和节点标号就可以对应上了,避免大家搞混**) +(**示例中节点编号是从1开始,所以为了让大家看的不晕,minDist数组下标我也从1开始计数,下标0就不使用了,这样下标和节点标号就可以对应上了,避免大家搞混**) -### 1 初始状态 +### 1 初始状态 -minDist 数组 里的数值初始化为 最大数,因为本题 节点距离不会超过 10000,所以 初始化最大数为 10001就可以。 +minDist数组里的数值初始化为最大数,因为本题节点距离不会超过10000,所以初始化最大数为10001就可以。 -相信这里录友就要问了,为什么这么做? +相信这里录友就要问了,为什么这么做? -现在 还没有最小生成树,默认每个节点距离最小生成树是最大的,这样后面我们在比较的时候,发现更近的距离,才能更新到 minDist 数组上。 +现在还没有最小生成树,默认每个节点距离最小生成树是最大的,这样后面我们在比较的时候,发现更近的距离,才能更新到minDist数组上。 如图: @@ -108,125 +108,125 @@ minDist 数组 里的数值初始化为 最大数,因为本题 节点距离不 1、prim三部曲,第一步:选距离生成树最近节点 -选择距离最小生成树最近的节点,加入到最小生成树,刚开始还没有最小生成树,所以随便选一个节点加入就好(因为每一个节点一定会在最小生成树里,所以随便选一个就好),那我们选择节点1 (符合遍历数组的习惯,第一个遍历的也是节点1) +选择距离最小生成树最近的节点,加入到最小生成树,刚开始还没有最小生成树,所以随便选一个节点加入就好(因为每一个节点一定会在最小生成树里,所以随便选一个就好),那我们选择节点1(符合遍历数组的习惯,第一个遍历的也是节点1) -2、prim三部曲,第二步:最近节点加入生成树 +2、prim三部曲,第二步:最近节点加入生成树 -此时 节点1 已经算最小生成树的节点。 +此时节点1已经算最小生成树的节点。 3、prim三部曲,第三步:更新非生成树节点到生成树的距离(即更新minDist数组) -接下来,我们要更新所有节点距离最小生成树的距离,如图: +接下来,我们要更新所有节点距离最小生成树的距离,如图: ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20231222102048.png) -注意下标0,我们就不管它了,下标 1 与节点 1 对应,这样可以避免大家把节点搞混。 +注意下标0,我们就不管它了,下标1与节点1对应,这样可以避免大家把节点搞混。 -此时所有非生成树的节点距离 最小生成树(节点1)的距离都已经跟新了 。 +此时所有非生成树的节点距离最小生成树(节点1)的距离都已经跟新了。 -* 节点2 与 节点1 的距离为1,比原先的 距离值10001小,所以更新minDist[2]。 -* 节点3 和 节点1 的距离为1,比原先的 距离值10001小,所以更新minDist[3]。 -* 节点5 和 节点1 的距离为2,比原先的 距离值10001小,所以更新minDist[5]。 +* 节点2与节点1的距离为1,比原先的距离值10001小,所以更新minDist[2]。 +* 节点3和节点1的距离为1,比原先的距离值10001小,所以更新minDist[3]。 +* 节点5和节点1的距离为2,比原先的距离值10001小,所以更新minDist[5]。 -**注意图中我标记了 minDist数组里更新的权值**,是哪两个节点之间的权值,例如 minDist[2] =1 ,这个 1 是 节点1 与 节点2 之间的连线,清楚这一点对最后我们记录 最小生成树的权值总和很重要。 +**注意图中我标记了minDist数组里更新的权值**,是哪两个节点之间的权值,例如minDist[2]=1,这个1是节点1与节点2之间的连线,清楚这一点对最后我们记录最小生成树的权值总和很重要。 -(我在后面依然会不断重复 prim三部曲,可能基础好的录友会感觉有点啰嗦,但也是让大家感觉这三部曲求解的过程) +(我在后面依然会不断重复prim三部曲,可能基础好的录友会感觉有点啰嗦,但也是让大家感觉这三部曲求解的过程) -### 3 +### 3 1、prim三部曲,第一步:选距离生成树最近节点 -选取一个距离 最小生成树(节点1) 最近的非生成树里的节点,节点2,3,5 距离 最小生成树(节点1) 最近,选节点 2(其实选 节点3或者节点2都可以,距离一样的)加入最小生成树。 +选取一个距离最小生成树(节点1)最近的非生成树里的节点,节点2,3,5距离最小生成树(节点1)最近,选节点2(其实选节点3或者节点2都可以,距离一样的)加入最小生成树。 -2、prim三部曲,第二步:最近节点加入生成树 +2、prim三部曲,第二步:最近节点加入生成树 -此时 节点1 和 节点2,已经算最小生成树的节点。 +此时节点1和节点2,已经算最小生成树的节点。 3、prim三部曲,第三步:更新非生成树节点到生成树的距离(即更新minDist数组) -接下来,我们要更新节点距离最小生成树的距离,如图: +接下来,我们要更新节点距离最小生成树的距离,如图: -![](https://code-thinking-1253855093.file.myqcloud.com/pics/20231222102431.png) +![](https://code-thinking-1253855093.file.myqcloud.com/pics/20231222102431.png) -此时所有非生成树的节点距离 最小生成树(节点1、节点2)的距离都已经跟新了 。 +此时所有非生成树的节点距离最小生成树(节点1、节点2)的距离都已经跟新了。 -* 节点3 和 节点2 的距离为2,和原先的距离值1 小,所以不用更新。 -* 节点4 和 节点2 的距离为2,比原先的距离值10001小,所以更新minDist[4]。 -* 节点5 和 节点2 的距离为10001(不连接),所以不用更新。 -* 节点6 和 节点2 的距离为1,比原先的距离值10001小,所以更新minDist[6]。 +* 节点3和节点2的距离为2,和原先的距离值1小,所以不用更新。 +* 节点4和节点2的距离为2,比原先的距离值10001小,所以更新minDist[4]。 +* 节点5和节点2的距离为10001(不连接),所以不用更新。 +* 节点6和节点2的距离为1,比原先的距离值10001小,所以更新minDist[6]。 -### 4 +### 4 1、prim三部曲,第一步:选距离生成树最近节点 -选择一个距离 最小生成树(节点1、节点2) 最近的非生成树里的节点,节点3,6 距离 最小生成树(节点1、节点2) 最近,选节点3 (选节点6也可以,距离一样)加入最小生成树。 +选择一个距离最小生成树(节点1、节点2)最近的非生成树里的节点,节点3,6距离最小生成树(节点1、节点2)最近,选节点3(选节点6也可以,距离一样)加入最小生成树。 -2、prim三部曲,第二步:最近节点加入生成树 +2、prim三部曲,第二步:最近节点加入生成树 -此时 节点1 、节点2 、节点3 算是最小生成树的节点。 +此时节点1、节点2、节点3算是最小生成树的节点。 3、prim三部曲,第三步:更新非生成树节点到生成树的距离(即更新minDist数组) -接下来更新节点距离最小生成树的距离,如图: +接下来更新节点距离最小生成树的距离,如图: -![](https://code-thinking-1253855093.file.myqcloud.com/pics/20231222102457.png) +![](https://code-thinking-1253855093.file.myqcloud.com/pics/20231222102457.png) -所有非生成树的节点距离 最小生成树(节点1、节点2、节点3 )的距离都已经跟新了 。 +所有非生成树的节点距离最小生成树(节点1、节点2、节点3)的距离都已经跟新了。 -* 节点 4 和 节点 3的距离为 1,和原先的距离值 2 小,所以更新minDist[4]为1。 +* 节点4和节点3的距离为1,和原先的距离值2小,所以更新minDist[4]为1。 -上面为什么我们只比较 节点4 和 节点3 的距离呢? +上面为什么我们只比较节点4和节点3的距离呢? -因为节点3加入 最小生成树后,非 生成树节点 只有 节点 4 和 节点3是链接的,所以需要重新更新一下 节点4距离最小生成树的距离,其他节点距离最小生成树的距离 都不变。 +因为节点3加入最小生成树后,非生成树节点只有节点4和节点3是链接的,所以需要重新更新一下节点4距离最小生成树的距离,其他节点距离最小生成树的距离都不变。 -### 5 +### 5 1、prim三部曲,第一步:选距离生成树最近节点 -继续选择一个距离 最小生成树(节点1、节点2、节点3) 最近的非生成树里的节点,为了巩固大家对 minDist数组的理解,这里我再啰嗦一遍: +继续选择一个距离最小生成树(节点1、节点2、节点3)最近的非生成树里的节点,为了巩固大家对minDist数组的理解,这里我再啰嗦一遍: -![](https://code-thinking-1253855093.file.myqcloud.com/pics/20231217213516.png) +![](https://code-thinking-1253855093.file.myqcloud.com/pics/20231217213516.png) -**minDist数组 是记录了 所有非生成树节点距离生成树的最小距离**,所以 从数组里我们能看出来,非生成树节点 4 和 节点 6 距离 生成树最近。 +**minDist数组是记录了所有非生成树节点距离生成树的最小距离**,所以从数组里我们能看出来,非生成树节点4和节点6距离生成树最近。 -任选一个加入生成树,我们选 节点4(选节点6也行) 。 +任选一个加入生成树,我们选节点4(选节点6也行)。 -**注意**,我们根据 minDist数组,选取距离 生成树 最近的节点 加入生成树,那么 **minDist数组里记录的其实也是 最小生成树的边的权值**(我在图中把权值对应的是哪两个节点也标记出来了)。 +**注意**,我们根据minDist数组,选取距离生成树最近的节点加入生成树,那么**minDist数组里记录的其实也是最小生成树的边的权值**(我在图中把权值对应的是哪两个节点也标记出来了)。 -如果大家不理解,可以跟着我们下面的讲解,看 minDist数组的变化, minDist数组 里记录的权值对应的哪条边。 +如果大家不理解,可以跟着我们下面的讲解,看minDist数组的变化,minDist数组里记录的权值对应的哪条边。 -理解这一点很重要,因为 最后我们要求 最小生成树里所有边的权值和。 +理解这一点很重要,因为最后我们要求最小生成树里所有边的权值和。 -2、prim三部曲,第二步:最近节点加入生成树 +2、prim三部曲,第二步:最近节点加入生成树 -此时 节点1、节点2、节点3、节点4 算是 最小生成树的节点。 +此时节点1、节点2、节点3、节点4算是最小生成树的节点。 3、prim三部曲,第三步:更新非生成树节点到生成树的距离(即更新minDist数组) -接下来更新节点距离最小生成树的距离,如图: +接下来更新节点距离最小生成树的距离,如图: -![](https://code-thinking-1253855093.file.myqcloud.com/pics/20231222102618.png) +![](https://code-thinking-1253855093.file.myqcloud.com/pics/20231222102618.png) -minDist数组已经更新了 所有非生成树的节点距离 最小生成树(节点1、节点2、节点3、节点4 )的距离 。 +minDist数组已经更新了所有非生成树的节点距离最小生成树(节点1、节点2、节点3、节点4)的距离。 -* 节点 5 和 节点 4的距离为 1,和原先的距离值 2 小,所以更新minDist[5]为1。 +* 节点5和节点4的距离为1,和原先的距离值2小,所以更新minDist[5]为1。 -### 6 +### 6 1、prim三部曲,第一步:选距离生成树最近节点 -继续选距离 最小生成树(节点1、节点2、节点3、节点4 )最近的非生成树里的节点,只有 节点 5 和 节点6。 +继续选距离最小生成树(节点1、节点2、节点3、节点4)最近的非生成树里的节点,只有节点5和节点6。 -选节点5 (选节点6也可以)加入 生成树。 +选节点5(选节点6也可以)加入生成树。 -2、prim三部曲,第二步:最近节点加入生成树 +2、prim三部曲,第二步:最近节点加入生成树 -节点1、节点2、节点3、节点4、节点5 算是 最小生成树的节点。 +节点1、节点2、节点3、节点4、节点5算是最小生成树的节点。 3、prim三部曲,第三步:更新非生成树节点到生成树的距离(即更新minDist数组) @@ -234,44 +234,44 @@ minDist数组已经更新了 所有非生成树的节点距离 最小生成树 ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20231222102646.png) -minDist数组已经更新了 所有非生成树的节点距离 最小生成树(节点1、节点2、节点3、节点4 、节点5)的距离 。 +minDist数组已经更新了所有非生成树的节点距离最小生成树(节点1、节点2、节点3、节点4、节点5)的距离。 -* 节点 6 和 节点 5 距离为 2,比原先的距离值 1 大,所以不更新 -* 节点 7 和 节点 5 距离为 1,比原先的距离值 10001小,更新 minDist[7] +* 节点6和节点5距离为2,比原先的距离值1大,所以不更新 +* 节点7和节点5距离为1,比原先的距离值10001小,更新minDist[7] -### 7 +### 7 1、prim三部曲,第一步:选距离生成树最近节点 -继续选距离 最小生成树(节点1、节点2、节点3、节点4 、节点5)最近的非生成树里的节点,只有 节点 6 和 节点7。 +继续选距离最小生成树(节点1、节点2、节点3、节点4、节点5)最近的非生成树里的节点,只有节点6和节点7。 -2、prim三部曲,第二步:最近节点加入生成树 +2、prim三部曲,第二步:最近节点加入生成树 -选节点6 (选节点7也行,距离一样的)加入生成树。 +选节点6(选节点7也行,距离一样的)加入生成树。 3、prim三部曲,第三步:更新非生成树节点到生成树的距离(即更新minDist数组) -节点1、节点2、节点3、节点4、节点5、节点6 算是 最小生成树的节点 ,接下来更新节点距离最小生成树的距离,如图: +节点1、节点2、节点3、节点4、节点5、节点6算是最小生成树的节点,接下来更新节点距离最小生成树的距离,如图: ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20231222102732.png) -这里就不在重复描述了,大家类推,最后,节点7加入生成树,如图: +这里就不在重复描述了,大家类推,最后,节点7加入生成树,如图: -![](https://code-thinking-1253855093.file.myqcloud.com/pics/20231222102820.png) +![](https://code-thinking-1253855093.file.myqcloud.com/pics/20231222102820.png) -### 最后 +### 最后 -最后我们就生成了一个 最小生成树, 绿色的边将所有节点链接到一起,并且 保证权值是最小的,因为我们在更新 minDist 数组的时候,都是选距离 最小生成树最近的点 加入到树中。 +最后我们就生成了一个最小生成树,绿色的边将所有节点链接到一起,并且保证权值是最小的,因为我们在更新minDist数组的时候,都是选距离最小生成树最近的点加入到树中。 -讲解上面的模拟过程的时候,我已经强调多次 minDist数组 是记录了 所有非生成树节点距离生成树的最小距离。 +讲解上面的模拟过程的时候,我已经强调多次minDist数组是记录了所有非生成树节点距离生成树的最小距离。 -最后,minDist数组 也就是记录的是最小生成树所有边的权值。 +最后,minDist数组也就是记录的是最小生成树所有边的权值。 -我在图中,特别把 每条边的权值对应的是哪两个节点 标记出来(例如minDist[7] = 1,对应的是节点5 和 节点7之间的边,而不是 节点6 和 节点7),为了就是让大家清楚, minDist里的每一个值 对应的是哪条边。 +我在图中,特别把每条边的权值对应的是哪两个节点标记出来(例如minDist[7]=1,对应的是节点5和节点7之间的边,而不是节点6和节点7),为了就是让大家清楚,minDist里的每一个值对应的是哪条边。 -那么我们要求最小生成树里边的权值总和 就是 把 最后的 minDist 数组 累加一起。 +那么我们要求最小生成树里边的权值总和就是把最后的minDist数组累加一起。 -以下代码,我对 prim三部曲,做了重点注释,大家根据这三步,就可以 透彻理解prim。 +以下代码,我对prim三部曲,做了重点注释,大家根据这三步,就可以透彻理解prim。 ```CPP #include @@ -338,52 +338,52 @@ int main() { } -``` +``` -时间复杂度为 O(n^2),其中 n 为节点数量。 +时间复杂度为O(n^2),其中n为节点数量。 ## 拓展 -上面讲解的是记录了最小生成树 所有边的权值,如果让打印出来 最小生成树的每条边呢? 或者说 要把这个最小生成树画出来呢? +上面讲解的是记录了最小生成树所有边的权值,如果让打印出来最小生成树的每条边呢?或者说要把这个最小生成树画出来呢? -此时我们就需要把 最小生成树里每一条边记录下来。 +此时我们就需要把最小生成树里每一条边记录下来。 -此时有两个问题: +此时有两个问题: -* 1、用什么结构来记录 -* 2、如何记录 +* 1、用什么结构来记录 +* 2、如何记录 -如果记录边,其实就是记录两个节点就可以,两个节点连成一条边。 +如果记录边,其实就是记录两个节点就可以,两个节点连成一条边。 如何记录两个节点呢? -我们使用一维数组就可以记录。 parent[节点编号] = 节点编号, 这样就把一条边记录下来了。(当然如果节点编号非常大,可以考虑使用map) +我们使用一维数组就可以记录。parent[节点编号] = 节点编号,这样就把一条边记录下来了。(当然如果节点编号非常大,可以考虑使用map) -使用一维数组记录是有向边,不过我们这里不需要记录方向,所以只关注两条边是连接的就行。 +使用一维数组记录是有向边,不过我们这里不需要记录方向,所以只关注两条边是连接的就行。 -parent数组初始化代码: +parent数组初始化代码: ```CPP vector parent(v + 1, -1); ``` -接下来就是第二个问题,如何记录? +接下来就是第二个问题,如何记录? -我们再来回顾一下 prim三部曲, +我们再来回顾一下prim三部曲, 1. 第一步,选距离生成树最近节点 -2. 第二步,最近节点加入生成树 +2. 第二步,最近节点加入生成树 3. 第三步,更新非生成树节点到生成树的距离(即更新minDist数组) -大家先思考一下,我们是在第几步,可以记录 最小生成树的边呢? +大家先思考一下,我们是在第几步,可以记录最小生成树的边呢? -在本面上半篇 我们讲解过:“我们根据 minDist数组,选组距离 生成树 最近的节点 加入生成树,那么 **minDist数组里记录的其实也是 最小生成树的边的权值**。” +在本面上半篇我们讲解过:“我们根据minDist数组,选组距离生成树最近的节点加入生成树,那么**minDist数组里记录的其实也是最小生成树的边的权值**。” -既然 minDist数组 记录了 最小生成树的边,是不是就是在更新 minDist数组 的时候,去更新parent数组来记录一下对应的边呢。 +既然minDist数组记录了最小生成树的边,是不是就是在更新minDist数组的时候,去更新parent数组来记录一下对应的边呢。 -所以 在 prim三部曲中的第三步,更新 parent数组,代码如下: +所以在prim三部曲中的第三步,更新parent数组,代码如下: ```CPP for (int j = 1; j <= v; j++) { @@ -394,23 +394,23 @@ for (int j = 1; j <= v; j++) { } ``` -代码中注释中,我强调了 数组指向的顺序很重要。 因为不少录友在这里会写成这样: `parent[cur] = j` 。 +代码中注释中,我强调了数组指向的顺序很重要。因为不少录友在这里会写成这样: `parent[cur] = j` 。 -这里估计大家会疑惑了,parent[节点编号A] = 节点编号B, 就表示A 和 B 相连,我们这里就不用在意方向,代码中 为什么 只能 `parent[j] = cur` 而不能 `parent[cur] = j` 这么写呢? +这里估计大家会疑惑了,parent[节点编号A] = 节点编号B,就表示A和B相连,我们这里就不用在意方向,代码中为什么只能 `parent[j] = cur` 而不能 `parent[cur] = j` 这么写呢? -如果写成 `parent[cur] = j`,在 for 循环中,有多个 j 满足要求, 那么 parent[cur] 就会被反复覆盖,因为 cur 是一个固定值。 +如果写成 `parent[cur] = j`,在for循环中,有多个j满足要求,那么 parent[cur] 就会被反复覆盖,因为cur是一个固定值。 -举个例子,cur = 1, 在 for循环中,可能 就 j = 2, j = 3,j =4 都符合条件,那么本来应该记录 节点1 与 节点 2、节点3、节点4相连的。 +举个例子,cur=1,在for循环中,可能就j=2,j=3,j=4都符合条件,那么本来应该记录节点1与节点2、节点3、节点4相连的。 -如果 `parent[cur] = j` 这么写,最后更新的逻辑是 parent[1] = 2, parent[1] = 3, parent[1] = 4, 最后只能记录 节点1 与节点 4 相连,其他相连情况都被覆盖了。 +如果 `parent[cur] = j` 这么写,最后更新的逻辑是 parent[1] = 2, parent[1] = 3, parent[1] = 4,最后只能记录节点1与节点4相连,其他相连情况都被覆盖了。 -如果这么写 `parent[j] = cur`, 那就是 parent[2] = 1, parent[3] = 1, parent[4] = 1 ,这样 才能完整表示出 节点1 与 其他节点都是链接的,才没有被覆盖。 +如果这么写 `parent[j] = cur`,那就是 parent[2] = 1, parent[3] = 1, parent[4] = 1 ,这样才能完整表示出节点1与其他节点都是链接的,才没有被覆盖。 主要问题也是我们使用了一维数组来记录。 -如果是二维数组,来记录两个点链接,例如 parent[节点编号A][节点编号B] = 1 ,parent[节点编号B][节点编号A] = 1,来表示 节点A 与 节点B 相连,那就没有上面说的这个注意事项了,当然这么做的话,就是多开辟的内存空间。 +如果是二维数组,来记录两个点链接,例如 parent[节点编号A][节点编号B] = 1 ,parent[节点编号B][节点编号A] = 1,来表示节点A与节点B相连,那就没有上面说的这个注意事项了,当然这么做的话,就是多开辟的内存空间。 -以下是输出最小生成树边的代码,不算最后输出, 就额外添加了两行代码,我都注释标记了: +以下是输出最小生成树边的代码,不算最后输出,就额外添加了两行代码,我都注释标记了: ```CPP #include @@ -460,7 +460,7 @@ int main() { } } -``` +``` 按照本题示例,代码输入如下: @@ -476,40 +476,40 @@ int main() { 注意,这里是无向图,我在输出上添加了箭头仅仅是为了方便大家看出是边的意思。 -大家可以和我们本题最后生成的最小生成树的图 去对比一下 边的链接情况: +大家可以和我们本题最后生成的最小生成树的图去对比一下边的链接情况: ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20231229115714.png) -绿色的边 是最小生成树,和我们的 输出完全一致。 +绿色的边是最小生成树,和我们的输出完全一致。 -## 总结 +## 总结 -此时我就把prim算法讲解完毕了,我们再来回顾一下。 +此时我就把prim算法讲解完毕了,我们再来回顾一下。 -关于 prim算法,我自创了三部曲,来帮助大家理解: +关于prim算法,我自创了三部曲,来帮助大家理解: 1. 第一步,选距离生成树最近节点 -2. 第二步,最近节点加入生成树 +2. 第二步,最近节点加入生成树 3. 第三步,更新非生成树节点到生成树的距离(即更新minDist数组) -大家只要理解这三部曲, prim算法 至少是可以写出一个框架出来,然后在慢慢补充细节,这样不至于 自己在写prim的时候 两眼一抹黑 完全凭感觉去写。 -这也为什么很多录友感觉 prim算法比较难,而且每次学会来,隔一段时间 又不会写了,主要是 没有一个纲领。 +大家只要理解这三部曲,prim算法至少是可以写出一个框架出来,然后在慢慢补充细节,这样不至于自己在写prim的时候两眼一抹黑完全凭感觉去写。 +这也为什么很多录友感觉prim算法比较难,而且每次学会来,隔一段时间又不会写了,主要是没有一个纲领。 -理解这三部曲之后,更重要的 就是理解 minDist数组。 +理解这三部曲之后,更重要的就是理解minDist数组。 -**minDist数组 是prim算法的灵魂,它帮助 prim算法完成最重要的一步,就是如何找到 距离最小生成树最近的点**。 +**minDist数组是prim算法的灵魂,它帮助prim算法完成最重要的一步,就是如何找到距离最小生成树最近的点**。 -再来帮大家回顾 minDist数组 的含义:记录 每一个节点距离最小生成树的最近距离。 +再来帮大家回顾minDist数组的含义:记录每一个节点距离最小生成树的最近距离。 -理解 minDist数组 ,至少大家看prim算法的代码不会懵。 +理解minDist数组,至少大家看prim算法的代码不会懵。 -也正是 因为 minDist数组 的作用,我们根据 minDist数组,选取距离 生成树 最近的节点 加入生成树,那么 **minDist数组里记录的其实也是 最小生成树的边的权值**。 +也正是因为minDist数组的作用,我们根据minDist数组,选取距离生成树最近的节点加入生成树,那么**minDist数组里记录的其实也是最小生成树的边的权值**。 -所以我们求 最小生成树的权值和 就是 计算后的 minDist数组 数值总和。 +所以我们求最小生成树的权值和就是计算后的minDist数组数值总和。 -最后我们拓展了如何求职 最小生成树 的每一条边,其实 添加的代码很简单,主要是理解 为什么使用 parent数组 来记录边 以及 在哪里 更新parent数组。 +最后我们拓展了如何获得最小生成树的每一条边,其实添加的代码很简单,主要是理解为什么使用parent数组来记录边以及在哪里更新parent数组。 -同时,因为使用一维数组,数组的下标和数组 如何赋值很重要,不要搞反,导致结果被覆盖。 +同时,因为使用一维数组,数组的下标和数组如何赋值很重要,不要搞反,导致结果被覆盖。 好了,以上为总结,录友们学习愉快。 From 419db364a32ee28abcdd03a0aa1f7823a5125552 Mon Sep 17 00:00:00 2001 From: programmercarl <826123027@qq.com> Date: Tue, 12 Nov 2024 10:06:56 +0800 Subject: [PATCH 60/65] Update --- README.md | 5 +-- problems/0093.复原IP地址.md | 3 +- problems/0416.分割等和子集.md | 44 +++++++++++-------- .../kamacoder/0047.参会dijkstra朴素.md | 2 +- .../0096.城市间货物运输III.md | 4 +- .../kamacoder/0126.骑士的攻击astar.md | 2 +- 6 files changed, 32 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 3bb575d1..8255bd5a 100644 --- a/README.md +++ b/README.md @@ -106,8 +106,8 @@ 4. [数组:977.有序数组的平方](./problems/0977.有序数组的平方.md) 5. [数组:209.长度最小的子数组](./problems/0209.长度最小的子数组.md) 6. [数组:区间和](./problems/kamacoder/0058.区间和.md) -6. [数组:59.螺旋矩阵II](./problems/0059.螺旋矩阵II.md) -8. [数组:开发商购买土地](./problems/kamacoder/0044.开发商购买土地.md) +7. [数组:开发商购买土地](./problems/kamacoder/0044.开发商购买土地.md) +8. [数组:59.螺旋矩阵II](./problems/0059.螺旋矩阵II.md) 9. [数组:总结篇](./problems/数组总结篇.md) ## 链表 @@ -196,7 +196,6 @@ 12. [二叉树:110.平衡二叉树](./problems/0110.平衡二叉树.md) 13. [二叉树:257.二叉树的所有路径](./problems/0257.二叉树的所有路径.md) 14. [本周总结!(二叉树)](./problems/周总结/20201003二叉树周末总结.md) -15. [二叉树:二叉树中递归带着回溯](./problems/二叉树中递归带着回溯.md) 16. [二叉树:404.左叶子之和](./problems/0404.左叶子之和.md) 17. [二叉树:513.找树左下角的值](./problems/0513.找树左下角的值.md) 18. [二叉树:112.路径总和](./problems/0112.路径总和.md) diff --git a/problems/0093.复原IP地址.md b/problems/0093.复原IP地址.md index eb81f4b6..a03a0e3b 100644 --- a/problems/0093.复原IP地址.md +++ b/problems/0093.复原IP地址.md @@ -376,9 +376,8 @@ class Solution { // 剪枝:ip段的长度最大是3,并且ip段处于[0,255] for (int i = start; i < s.length() && i - start < 3 && Integer.parseInt(s.substring(start, i + 1)) >= 0 && Integer.parseInt(s.substring(start, i + 1)) <= 255; i++) { - // 如果ip段的长度大于1,并且第一位为0的话,continue if (i + 1 - start > 1 && s.charAt(start) - '0' == 0) { - continue; + break; } stringBuilder.append(s.substring(start, i + 1)); // 当stringBuilder里的网段数量小于3时,才会加点;如果等于3,说明已经有3段了,最后一段不需要再加点 diff --git a/problems/0416.分割等和子集.md b/problems/0416.分割等和子集.md index 5bd7ff6c..55ed7ad2 100644 --- a/problems/0416.分割等和子集.md +++ b/problems/0416.分割等和子集.md @@ -47,7 +47,13 @@ 那么只要找到集合里能够出现 sum / 2 的子集总和,就算是可以分割成两个相同元素和子集了。 -本题是可以用回溯暴力搜索出所有答案的,但最后超时了,也不想再优化了,放弃回溯,直接上01背包吧。 +本题是可以用回溯暴力搜索出所有答案的,但最后超时了,也不想再优化了,放弃回溯。 + +是否有其他解法可以解决此题。 + +本题的本质是,能否把容量为 sum / 2的背包装满。 + +**这是 背包算法可以解决的经典类型题目**。 如果对01背包不够了解,建议仔细看完如下两篇: @@ -56,7 +62,7 @@ ### 01背包问题 -背包问题,大家都知道,有N件物品和一个最多能背重量为W 的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。每件物品只能用一次,求解将哪些物品装入背包里物品价值总和最大。 +01背包问题,大家都知道,有N件物品和一个最多能背重量为W 的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。每件物品只能用一次,求解将哪些物品装入背包里物品价值总和最大。 **背包问题有多种背包方式,常见的有:01背包、完全背包、多重背包、分组背包和混合背包等等。** @@ -64,32 +70,33 @@ **即一个商品如果可以重复多次放入是完全背包,而只能放入一次是01背包,写法还是不一样的。** -**要明确本题中我们要使用的是01背包,因为元素我们只能用一次。** +**元素我们只能用一次,如果使用背包,那么也是01背包** 回归主题:首先,本题要求集合里能否出现总和为 sum / 2 的子集。 -那么来一一对应一下本题,看看背包问题如何来解决。 +既有一个 只能装重量为 sum / 2 的背包,商品为数字,这些数字能不能把 这个背包装满。 -**只有确定了如下四点,才能把01背包问题套到本题上来。** +那每一件商品是数字的话,对应的重量 和 价值是多少呢? -* 背包的体积为sum / 2 -* 背包要放入的商品(集合里的元素)重量为 元素的数值,价值也为元素的数值 -* 背包如果正好装满,说明找到了总和为 sum / 2 的子集。 -* 背包中每一个元素是不可重复放入。 +一个数字只有一个维度,即 重量等于价值。 -以上分析完,我们就可以套用01背包,来解决这个问题了。 +当数字 可以装满 承载重量为 sum / 2 的背包的背包时,这个背包的价值也是 sum / 2。 + +那么这道题就是 装满 承载重量为 sum / 2 的背包,价值最大是多少? + +如果最大价值是 sum / 2,说明正好被商品装满了。 + +因为商品是数字,重量和对应的价值是相同的。 + +以上分析完,我们就可以直接用01背包 来解决这个问题了。 动规五部曲分析如下: 1. 确定dp数组以及下标的含义 -01背包中,dp[j] 表示: 容量为j的背包,所背的物品价值最大可以为dp[j]。 +01背包中,dp[j] 表示: 容量(所能装的重量)为j的背包,所背的物品价值最大可以为dp[j]。 -本题中每一个元素的数值既是重量,也是价值。 - -**套到本题,dp[j]表示 背包总容量(所能装的总重量)是j,放进物品后,背的最大重量为dp[j]**。 - -那么如果背包容量为target, dp[target]就是装满 背包之后的重量,所以 当 dp[target] == target 的时候,背包就装满了。 +如果背包所载重量为target, dp[target]就是装满 背包之后的总价值,因为 本题中每一个元素的数值既是重量,也是价值,所以,当 dp[target] == target 的时候,背包就装满了。 有录友可能想,那还有装不满的时候? @@ -192,12 +199,11 @@ public: ## 总结 -这道题目就是一道01背包应用类的题目,需要我们拆解题目,然后套入01背包的场景。 +这道题目就是一道01背包经典应用类的题目,需要我们拆解题目,然后才能发现可以使用01背包。 01背包相对于本题,主要要理解,题目中物品是nums[i],重量是nums[i],价值也是nums[i],背包体积是sum/2。 -看代码的话,就可以发现,基本就是按照01背包的写法来的。 - +做完本题后,需要大家清晰:背包问题,不仅可以求 背包能被的最大价值,还可以求这个背包是否可以装满。 ## 其他语言版本 diff --git a/problems/kamacoder/0047.参会dijkstra朴素.md b/problems/kamacoder/0047.参会dijkstra朴素.md index c0a490b3..eb2d51cf 100644 --- a/problems/kamacoder/0047.参会dijkstra朴素.md +++ b/problems/kamacoder/0047.参会dijkstra朴素.md @@ -578,7 +578,7 @@ int main() { 更新 minDist数组,即:源点(节点1) 到 节点2 和 节点3的距离。 * 源点到节点2的最短距离为100,小于原minDist[2]的数值max,更新minDist[2] = 100 -* 源点到节点3的最短距离为1,小于原minDist[3]的数值max,更新minDist[4] = 1 +* 源点到节点3的最短距离为1,小于原minDist[3]的数值max,更新minDist[3] = 1 ------------------- diff --git a/problems/kamacoder/0096.城市间货物运输III.md b/problems/kamacoder/0096.城市间货物运输III.md index dacd23d1..60c997a5 100644 --- a/problems/kamacoder/0096.城市间货物运输III.md +++ b/problems/kamacoder/0096.城市间货物运输III.md @@ -215,9 +215,9 @@ int main() { ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20240409111849.png) -边:节点3 -> 节点4,权值为1 ,minDist[4] > minDist[3] + 1,更新 minDist[4] = 0 + (-1) = -1 ,如图: +边:节点3 -> 节点4,权值为1 ,minDist[4] > minDist[3] + 1,更新 minDist[4] = 0 + 1 = 1 ,如图: -![](https://code-thinking-1253855093.file.myqcloud.com/pics/20240409111837.png) +![](https://code-thinking-1253855093.file.myqcloud.com/pics/20241018192042.png) 以上是对所有边进行的第一次松弛,最后 minDist数组为 :-1 -1 0 1 ,(从下标1算起) diff --git a/problems/kamacoder/0126.骑士的攻击astar.md b/problems/kamacoder/0126.骑士的攻击astar.md index 2d0481ec..8d53276c 100644 --- a/problems/kamacoder/0126.骑士的攻击astar.md +++ b/problems/kamacoder/0126.骑士的攻击astar.md @@ -173,7 +173,7 @@ int n=q.front();q.pop(); G:起点达到目前遍历节点的距离 -F:目前遍历的节点到达终点的距离 +H:目前遍历的节点到达终点的距离 起点达到目前遍历节点的距离 + 目前遍历的节点到达终点的距离 就是起点到达终点的距离。 From 6901cb345efc05009c029ee121592e3f66ec182a Mon Sep 17 00:00:00 2001 From: lllyt8 Date: Sun, 17 Nov 2024 23:30:11 -0800 Subject: [PATCH 61/65] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=E4=B8=AD?= =?UTF-8?q?=E6=96=87=E5=8D=95=E8=AF=8D=E5=86=97=E4=BD=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0647.回文子串.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/problems/0647.回文子串.md b/problems/0647.回文子串.md index 89e4ad11..c1f29a25 100644 --- a/problems/0647.回文子串.md +++ b/problems/0647.回文子串.md @@ -102,7 +102,7 @@ dp[i][j]可以初始化为true么? 当然不行,怎能刚开始就全都匹 4. 确定遍历顺序 -遍历顺序可有有点讲究了。 +遍历顺序可就有点讲究了。 首先从递推公式中可以看出,情况三是根据dp[i + 1][j - 1]是否为true,在对dp[i][j]进行赋值true的。 From 47605060055da15ad606684f92ebde27b5bd213d Mon Sep 17 00:00:00 2001 From: xi-mad <1171866049@qq.com> Date: Mon, 18 Nov 2024 16:50:05 +0800 Subject: [PATCH 62/65] =?UTF-8?q?Update=20=E8=83=8C=E5=8C=85=E7=90=86?= =?UTF-8?q?=E8=AE=BA=E5=9F=BA=E7=A1=8001=E8=83=8C=E5=8C=85-1.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修正错误 --- problems/背包理论基础01背包-1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/problems/背包理论基础01背包-1.md b/problems/背包理论基础01背包-1.md index 2747f179..a956013a 100644 --- a/problems/背包理论基础01背包-1.md +++ b/problems/背包理论基础01背包-1.md @@ -87,7 +87,7 @@ leetcode上没有纯01背包的问题,都是01背包应用方面的题目, i 来表示物品、j表示背包容量。 -(如果想用j 表示物品,j表示背包容量 行不行? 都可以的,个人习惯而已) +(如果想用j 表示物品,i 表示背包容量 行不行? 都可以的,个人习惯而已) 我们来尝试把上面的 二维表格填写一下。 From 5e0ab494756cb48b11450f997f56c2677f51dcc4 Mon Sep 17 00:00:00 2001 From: Lane Zhang Date: Fri, 22 Nov 2024 10:57:51 +0800 Subject: [PATCH 63/65] =?UTF-8?q?0123,=200188,=200309=20=E8=82=A1=E7=A5=A8?= =?UTF-8?q?=E7=B1=BB=E9=97=AE=E9=A2=98=EF=BC=8C=E5=A2=9E=E5=8A=A0=E6=98=93?= =?UTF-8?q?=E7=90=86=E8=A7=A3=E7=9A=84=E4=B8=80=E7=BB=B4=20dp=20Python=20?= =?UTF-8?q?=E5=92=8C=20Go=20=E7=89=88=E6=9C=AC=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../0123.买卖股票的最佳时机III.md | 29 +++++++++- .../0188.买卖股票的最佳时机IV.md | 56 +++++++++++++++++-- ...09.最佳买卖股票时机含冷冻期.md | 35 +++++++++++- 3 files changed, 110 insertions(+), 10 deletions(-) diff --git a/problems/0123.买卖股票的最佳时机III.md b/problems/0123.买卖股票的最佳时机III.md index 8e224a89..1b7c09d2 100644 --- a/problems/0123.买卖股票的最佳时机III.md +++ b/problems/0123.买卖股票的最佳时机III.md @@ -316,8 +316,9 @@ class Solution: ### Go: +> 版本一 + ```go -// 版本一 func maxProfit(prices []int) int { dp := make([][]int, len(prices)) for i := 0; i < len(prices); i++ { @@ -345,8 +346,9 @@ func max(a, b int) int { } ``` +> 版本二 + ```go -// 版本二 func maxProfit(prices []int) int { if len(prices) == 0 { return 0 @@ -371,8 +373,9 @@ func max(x, y int) int { } ``` +> 版本三 + ```go -// 版本三 func maxProfit(prices []int) int { if len(prices) == 0 { return 0 @@ -397,6 +400,26 @@ func max(x, y int) int { } ``` +> 版本四:一维 dp 易懂版本 + +```go +func maxProfit(prices []int) int { + dp := make([]int, 4) + dp[0] = -prices[0] + dp[2] = -prices[0] + + for _, price := range prices[1:] { + dc := slices.Clone(dp) // 这句话是关键,把前一天的 dp 状态保存下来,防止被覆盖掉,后面只用它,不用 dp,逻辑简单易懂 + dp[0] = max(dc[0], -price) + dp[1] = max(dc[1], dc[0] + price) + dp[2] = max(dc[2], dc[1] - price) + dp[3] = max(dc[3], dc[2] + price) + } + + return dp[3] +} +``` + ### JavaScript: > 版本一: diff --git a/problems/0188.买卖股票的最佳时机IV.md b/problems/0188.买卖股票的最佳时机IV.md index 0b1622ac..cbba12c9 100644 --- a/problems/0188.买卖股票的最佳时机IV.md +++ b/problems/0188.买卖股票的最佳时机IV.md @@ -297,8 +297,7 @@ class Solution { ### Python: -版本一 - +> 版本一 ```python class Solution: def maxProfit(self, k: int, prices: List[int]) -> int: @@ -313,7 +312,8 @@ class Solution: dp[i][j+2] = max(dp[i-1][j+2], dp[i-1][j+1] + prices[i]) return dp[-1][2*k] ``` -版本二 + +> 版本二 ```python class Solution: def maxProfit(self, k: int, prices: List[int]) -> int: @@ -329,9 +329,31 @@ class Solution: dp[j] = max(dp[j],dp[j-1]+prices[i]) return dp[2*k] ``` + +> 版本三: 一维 dp 数组(易理解版本) +```python +class Solution: + def maxProfit(self, k: int, prices: List[int]) -> int: + dp = [0] * k * 2 + for i in range(k): + dp[i * 2] = -prices[0] + + for price in prices[1:]: + dc = dp.copy() # 这句话是关键,把前一天的 dp 状态保存下来,防止被覆盖掉,后面只用它,不用 dp,逻辑简单易懂 + + for i in range(2 * k): + if i % 2 == 1: + dp[i] = max(dc[i], dc[i - 1] + price) + else: + pre = 0 if i == 0 else dc[i - 1] + dp[i] = max(dc[i], pre - price) + + return dp[-1] +``` + ### Go: -版本一: +> 版本一: ```go // 买卖股票的最佳时机IV 动态规划 @@ -368,7 +390,7 @@ func max(a, b int) int { } ``` -版本二: 三维 dp数组 +> 版本二: 三维 dp数组 ```go func maxProfit(k int, prices []int) int { length := len(prices) @@ -443,7 +465,31 @@ func max(a, b int) int { } ``` +> 版本四:一维 dp 数组(易理解版本) +```go +func maxProfit(k int, prices []int) int { + dp := make([]int, 2 * k) + for i := range k { + dp[i * 2] = -prices[0] + } + + for j := 1; j < len(prices); j++ { + dc := slices.Clone(dp) // 这句话是关键,把前一天的 dp 状态保存下来,防止被覆盖掉,后面只用它,不用 dp,逻辑简单易懂 + + for i := range k * 2 { + if i % 2 == 1 { + dp[i] = max(dc[i], dc[i - 1] + prices[j]) + } else { + pre := 0; if i >= 1 { pre = dc[i - 1] } + dp[i] = max(dc[i], pre - prices[j]) + } + } + } + + return dp[2 * k - 1] +} +``` ### JavaScript: diff --git a/problems/0309.最佳买卖股票时机含冷冻期.md b/problems/0309.最佳买卖股票时机含冷冻期.md index 4913b8bd..707b1532 100644 --- a/problems/0309.最佳买卖股票时机含冷冻期.md +++ b/problems/0309.最佳买卖股票时机含冷冻期.md @@ -274,7 +274,7 @@ class Solution { ``` ### Python: -版本一 +> 版本一 ```python from typing import List @@ -294,7 +294,8 @@ class Solution: return max(dp[n-1][3], dp[n-1][1], dp[n-1][2]) # 返回最后一天不持有股票的最大利润 ``` -版本二 + +> 版本二 ```python class Solution: def maxProfit(self, prices: List[int]) -> int: @@ -320,6 +321,36 @@ class Solution: return max(dp[-1][1], dp[-1][2]) ``` + +> 版本三 +```python +class Solution: + def maxProfit(self, prices: List[int]) -> int: + # 0: holding stocks + # (1) keep holding stocks: dp[i][0] = dp[i - 1][0] + # (2) buy stocks: dp[i][0] = dp[i - 1][1] - price, or dp[i - 1][3] - price + # 1: keep no stocks: dp[i][1] = dp[i - 1][1] + # 2: sell stocks: dp[i][2] = dp[i - 1][0] + price + # 3: cooldown day: dp[i][3] = dp[i - 1][2] + dp = [-prices[0], 0, 0, 0] + + for price in prices[1:]: + dc = dp.copy() # 这句话是关键,把前一天的 dp 状态保存下来,防止被覆盖掉,后面只用它,不用 dp,逻辑简单易懂 + dp[0] = max( + dc[0], + dc[1] - price, + dc[3] - price + ) + dp[1] = max( + dc[1], + dc[3] + ) + dp[2] = dc[0] + price + dp[3] = dc[2] + + return max(dp) +``` + ### Go: ```go From e40ddd5cbf46ae62a0b1aee4b683fb899b6fd6c8 Mon Sep 17 00:00:00 2001 From: Lane Zhang Date: Fri, 22 Nov 2024 10:59:16 +0800 Subject: [PATCH 64/65] =?UTF-8?q?0337.=E6=89=93=E5=AE=B6=E5=8A=AB=E8=88=8D?= =?UTF-8?q?III.md=20=E4=BD=BF=E7=94=A8=20`slices.Max`=20=E6=9B=BF=E4=BB=A3?= =?UTF-8?q?=E6=89=8B=E5=B7=A5max=20func=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0337.打家劫舍III.md | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/problems/0337.打家劫舍III.md b/problems/0337.打家劫舍III.md index 12e31aba..a3130df7 100644 --- a/problems/0337.打家劫舍III.md +++ b/problems/0337.打家劫舍III.md @@ -477,14 +477,7 @@ func max(x, y int) int { ```go func rob(root *TreeNode) int { res := robTree(root) - return max(res[0], res[1]) -} - -func max(a, b int) int { - if a > b { - return a - } - return b + return slices.Max(res) } func robTree(cur *TreeNode) []int { @@ -498,7 +491,7 @@ func robTree(cur *TreeNode) []int { // 考虑去偷当前的屋子 robCur := cur.Val + left[0] + right[0] // 考虑不去偷当前的屋子 - notRobCur := max(left[0], left[1]) + max(right[0], right[1]) + notRobCur := slices.Max(left) + slices.Max(right) // 注意顺序:0:不偷,1:去偷 return []int{notRobCur, robCur} From 332302b998306ca16e253deeff637075ee49e555 Mon Sep 17 00:00:00 2001 From: Lane Zhang Date: Fri, 22 Nov 2024 10:59:39 +0800 Subject: [PATCH 65/65] =?UTF-8?q?=E5=8A=A8=E6=80=81=E8=A7=84=E5=88=92?= =?UTF-8?q?=E7=90=86=E8=AE=BA=E5=9F=BA=E7=A1=80.md=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E4=B8=80=E4=B8=AA=E9=94=99=E5=AD=97=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/动态规划理论基础.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/problems/动态规划理论基础.md b/problems/动态规划理论基础.md index c9420d24..9ffb4533 100644 --- a/problems/动态规划理论基础.md +++ b/problems/动态规划理论基础.md @@ -106,7 +106,7 @@ **如果这灵魂三问自己都做到了,基本上这道题目也就解决了**,或者更清晰的知道自己究竟是哪一点不明白,是状态转移不明白,还是实现代码不知道该怎么写,还是不理解遍历dp数组的顺序。 -然后在问问题,目的性就很强了,群里的小伙伴也可以快速知道提问者的疑惑了。 +然后再问问题,目的性就很强了,群里的小伙伴也可以快速知道提问者的疑惑了。 **注意这里不是说不让大家问问题哈, 而是说问问题之前要有自己的思考,问题要问到点子上!**