From c4da16fd1abd3d3609eaa2f4cddf5d69dcaf320f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=BB=E7=BB=8D=E8=BE=B0?= Date: Tue, 24 Oct 2023 20:20:38 -0400 Subject: [PATCH 01/10] =?UTF-8?q?Problem=200827=20=E6=9C=80=E5=A4=A7?= =?UTF-8?q?=E4=BA=BA=E5=B7=A5=E5=B2=9B=E5=B1=BF=EF=BC=8C=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?python=E8=A7=A3=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0827.最大人工岛.md | 62 ++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/problems/0827.最大人工岛.md b/problems/0827.最大人工岛.md index d7879825..7206bf09 100644 --- a/problems/0827.最大人工岛.md +++ b/problems/0827.最大人工岛.md @@ -282,6 +282,68 @@ class Solution { } ``` +### Python + +```Python +class Solution(object): + # 可能的移动方向 + DIRECTIONS = [(1, 0), (-1, 0), (0, 1), (0, -1)] + + def exploreIsland(self, row, col, grid, visited, island_id): + """ + 从给定的单元格开始,使用深度优先搜索探索岛屿。 + """ + if (row < 0 or row >= len(grid) or col < 0 or col >= len(grid[0]) or + visited[row][col] or grid[row][col] == 0): + return 0 + + visited[row][col] = True + grid[row][col] = island_id + island_size = 1 + for dr, dc in self.DIRECTIONS: + island_size += self.exploreIsland(row + dr, col + dc, grid, visited, island_id) + return island_size + + def largestIsland(self, grid): + """ + 通过最多将一个0更改为1,找到可以形成的最大岛屿的大小。 + """ + rows, cols = len(grid), len(grid[0]) + island_sizes = {} + island_id = 2 # 从2开始标记岛屿(因为0代表水,1代表未被发现的陆地) + is_all_land = True + visited = [[False] * cols for _ in range(rows)] + + # 标记每个岛屿并存储其大小 + for r in range(rows): + for c in range(cols): + if grid[r][c] == 0: + is_all_land = False + elif not visited[r][c] and grid[r][c] == 1: + island_size = self.exploreIsland(r, c, grid, visited, island_id) + island_sizes[island_id] = island_size + island_id += 1 + + # 如果整个网格是陆地,则返回其大小 + if is_all_land: + return rows * cols + + # 计算可以通过将一个0更改为1来形成的最大岛屿 + max_island_size = 0 + for r in range(rows): + for c in range(cols): + if grid[r][c] == 0: + adjacent_islands = set() + for dr, dc in self.DIRECTIONS: + nr, nc = r + dr, c + dc + if 0 <= nr < rows and 0 <= nc < cols and grid[nr][nc] > 1: + adjacent_islands.add(grid[nr][nc]) + new_island_size = sum(island_sizes[island] for island in adjacent_islands) + 1 + max_island_size = max(max_island_size, new_island_size) + + return max_island_size +``` +

From 28d50d34c69714bbd11453451fc3fb7dedaad369 Mon Sep 17 00:00:00 2001 From: huawuque404 Date: Thu, 26 Oct 2023 19:15:25 +0800 Subject: [PATCH 02/10] Error changing Java code --- problems/0019.删除链表的倒数第N个节点.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/problems/0019.删除链表的倒数第N个节点.md b/problems/0019.删除链表的倒数第N个节点.md index dbd053d1..28bb61ee 100644 --- a/problems/0019.删除链表的倒数第N个节点.md +++ b/problems/0019.删除链表的倒数第N个节点.md @@ -110,7 +110,7 @@ public ListNode removeNthFromEnd(ListNode head, int n){ fastIndex = fastIndex.next; } - while (fastIndex.next != null){ + while (fastIndex != null){ fastIndex = fastIndex.next; slowIndex = slowIndex.next; } From 54144f3a6b59bb8be22111a489d60edc49eeffa9 Mon Sep 17 00:00:00 2001 From: Relsola Date: Fri, 27 Oct 2023 19:49:03 +0800 Subject: [PATCH 03/10] =?UTF-8?q?Update=2098.=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=20=E5=A2=9E=E5=8A=A0js?= =?UTF-8?q?=E5=92=8Cts=E8=BF=AD=E4=BB=A3=E8=A7=A3=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0098.验证二叉搜索树.md | 61 ++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/problems/0098.验证二叉搜索树.md b/problems/0098.验证二叉搜索树.md index 0a64266e..184060a5 100644 --- a/problems/0098.验证二叉搜索树.md +++ b/problems/0098.验证二叉搜索树.md @@ -595,6 +595,43 @@ var isValidBST = function (root) { }; ``` +> 迭代法: + +```JavaScript +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} root + * @return {boolean} + */ +let pre = null; +var isValidBST = function (root) { + const queue = []; + let cur = root; + let pre = null; + while (cur !== null || queue.length !== 0) { + if (cur !== null) { + queue.push(cur); + cur = cur.left; + } else { + cur = queue.pop(); + if (pre !== null && cur.val <= pre.val) { + return false; + } + pre = cur; + cur = cur.right; + } + } + return true; +}; +``` + ### TypeScript > 辅助数组解决: @@ -637,6 +674,30 @@ function isValidBST(root: TreeNode | null): boolean { }; ``` +> 迭代法: + +```TypeScript +function isValidBST(root: TreeNode | null): boolean { + const queue: TreeNode[] = []; + let cur: TreeNode | null = root; + let pre: TreeNode | null = null; + while (cur !== null || queue.length !== 0) { + if (cur !== null) { + queue.push(cur); + cur = cur.left; + } else { + cur = queue.pop()!; + if (pre !== null && cur!.val <= pre.val) { + return false; + } + pre = cur; + cur = cur!.right; + } + } + return true; +} +``` + ### Scala 辅助数组解决: From 1f9f95c0b285f3953f77e1111c37e01e1683e2f8 Mon Sep 17 00:00:00 2001 From: yunfeidog <1844025705@qq.com> Date: Sat, 28 Oct 2023 17:56:52 +0800 Subject: [PATCH 04/10] =?UTF-8?q?Update0239=E6=BB=91=E5=8A=A8=E7=AA=97?= =?UTF-8?q?=E5=8F=A3=E6=9C=80=E5=A4=A7=E5=80=BC=EF=BC=9A=E5=AD=98=E5=9C=A8?= =?UTF-8?q?=E5=8D=95=E8=B0=83=E9=98=9F=E5=88=97=E5=B9=B6=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?C++=E5=8D=95=E8=B0=83=E9=98=9F=E5=88=97=E8=A7=A3=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0239.滑动窗口最大值.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/problems/0239.滑动窗口最大值.md b/problems/0239.滑动窗口最大值.md index 6f420479..dbd036ee 100644 --- a/problems/0239.滑动窗口最大值.md +++ b/problems/0239.滑动窗口最大值.md @@ -65,6 +65,10 @@ public: 这么个队列香不香,要是有现成的这种数据结构是不是更香了! **可惜了,没有! 我们需要自己实现这么个队列。** +> 其实有这种数据结构的,在C++中,可以使用可以使用multiset这种数据结构作为单调队列 +> + 多重集合(`multiset`) 用以有序地存储元素的容器。允许存在相等的元素。 +> +> 在遍历原数组的时候,只需要把窗口的头元素加入到multiset中,然后把窗口的尾元素删除即可。因为multiset是有序的,并且提供了*rbegin(),可以直接获取窗口最大值。 然后再分析一下,队列里的元素一定是要排序的,而且要最大值放在出队口,要不然怎么知道最大值呢。 @@ -839,6 +843,24 @@ impl Solution { } ``` +### C++ +使用multiset作为单调队列 +```cpp +class Solution { +public: + vector maxSlidingWindow(vector& nums, int k) { + multiset st; + vector ans; + for (int i = 0; i < nums.size(); i++) { + if (i >= k) st.erase(st.find(nums[i - k])); + st.insert(nums[i]); + if (i >= k - 1) ans.push_back(*st.rbegin()); + } + return ans; + } +}; +``` +

From 1eb14f9fe287c4bacbdf788841b58e1819c3c0db Mon Sep 17 00:00:00 2001 From: xin Date: Sat, 28 Oct 2023 18:29:48 +0800 Subject: [PATCH 05/10] =?UTF-8?q?add:=201035.=E4=B8=8D=E7=9B=B8=E4=BA=A4?= =?UTF-8?q?=E7=BA=BF=E6=96=B0=E5=A2=9Etypescript=E6=BB=9A=E5=8A=A8?= =?UTF-8?q?=E6=95=B0=E7=BB=84=E5=86=99=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/1035.不相交的线.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/problems/1035.不相交的线.md b/problems/1035.不相交的线.md index ff9e5dc4..cccc7f8c 100644 --- a/problems/1035.不相交的线.md +++ b/problems/1035.不相交的线.md @@ -221,6 +221,8 @@ const maxUncrossedLines = (nums1, nums2) => { ### TypeScript: +> 二维数组 + ```typescript function maxUncrossedLines(nums1: number[], nums2: number[]): number { /** @@ -243,6 +245,33 @@ function maxUncrossedLines(nums1: number[], nums2: number[]): number { }; ``` +> 滚动数组 +```typescript +function maxUncrossedLines(nums1: number[], nums2: number[]): number { + const len1 = nums1.length + const len2 = nums2.length + + const dp: number[] = new Array(len2 + 1).fill(0) + + for (let i = 1; i <= len1; i++) { + let prev: number = 0; + let temp: number = 0; + for (let j = 1; j <= len2; j++) { + // 保存当前状态未计算前的值 + temp = dp[j] + // 使用没有累加的值进行累加 + if (nums1[i - 1] === nums2[j - 1]) dp[j] = prev + 1 + // dp[j] 表示之前的 dp[i][j-1],dp[j-1] 表示 dp[i-1][j] + else dp[j] = Math.max(dp[j], dp[j - 1]) + // 下一个元素使用前一个状态未计算的值 + prev = temp + } + } + return dp[len2] +} +``` + +

From 22ac5d47548c0f6d8d1dcc2f0649c5bb297862c5 Mon Sep 17 00:00:00 2001 From: xin Date: Sat, 28 Oct 2023 18:31:15 +0800 Subject: [PATCH 06/10] =?UTF-8?q?fix:=200053.=E6=9C=80=E5=A4=A7=E5=AD=90?= =?UTF-8?q?=E5=BA=8F=E5=92=8C=E5=8E=9Ftypescript=E8=BF=87=E4=B8=8D?= =?UTF-8?q?=E4=BA=86leetcode=EF=BC=8C=E6=9B=B4=E6=96=B0=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../0053.最大子序和(动态规划).md | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/problems/0053.最大子序和(动态规划).md b/problems/0053.最大子序和(动态规划).md index f1b64709..70ad7a84 100644 --- a/problems/0053.最大子序和(动态规划).md +++ b/problems/0053.最大子序和(动态规划).md @@ -226,18 +226,20 @@ object Solution { ```typescript function maxSubArray(nums: number[]): number { - /** - dp[i]:以nums[i]结尾的最大和 - */ - const dp: number[] = [] - dp[0] = nums[0]; - let resMax: number = 0; - for (let i = 1; i < nums.length; i++) { - dp[i] = Math.max(dp[i - 1] + nums[i], nums[i]); - resMax = Math.max(resMax, dp[i]); + const len = nums.length + if (len === 1) return nums[0] + + const dp: number[] = new Array(len) + let resMax: number = dp[0] = nums[0] + + for (let i = 1; i < len; i++) { + dp[i] = Math.max(dp[i - 1] + nums[i], nums[i]) + // 注意值为负数的情况 + if (dp[i] > resMax) resMax = dp[i] } - return resMax; -}; + + return resMax +} ``` From ddaba36a1257d04feea3d695f9dd072e3911ced2 Mon Sep 17 00:00:00 2001 From: xin <59196051+xin0907@users.noreply.github.com> Date: Sun, 29 Oct 2023 11:35:39 +0800 Subject: [PATCH 07/10] =?UTF-8?q?Update=201035.=E4=B8=8D=E7=9B=B8=E4=BA=A4?= =?UTF-8?q?=E7=9A=84=E7=BA=BF.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 更新 1035.不相交的线 typescript 代码注释 --- problems/1035.不相交的线.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/problems/1035.不相交的线.md b/problems/1035.不相交的线.md index cccc7f8c..e0625a2b 100644 --- a/problems/1035.不相交的线.md +++ b/problems/1035.不相交的线.md @@ -257,13 +257,14 @@ function maxUncrossedLines(nums1: number[], nums2: number[]): number { let prev: number = 0; let temp: number = 0; for (let j = 1; j <= len2; j++) { - // 保存当前状态未计算前的值 + // 备份一下当前状态(经过上层迭代后的) temp = dp[j] - // 使用没有累加的值进行累加 + // prev 相当于 dp[j-1](累加了上层的状态) + // 如果单纯 dp[j-1] 则不会包含上层状态 if (nums1[i - 1] === nums2[j - 1]) dp[j] = prev + 1 // dp[j] 表示之前的 dp[i][j-1],dp[j-1] 表示 dp[i-1][j] else dp[j] = Math.max(dp[j], dp[j - 1]) - // 下一个元素使用前一个状态未计算的值 + // 继续使用上一层状态更新参数用于当前层下一个状态 prev = temp } } From ef1c72a36b6fcc11ad2e45ac48f12630f24e6cc9 Mon Sep 17 00:00:00 2001 From: xin Date: Sun, 29 Oct 2023 17:40:58 +0800 Subject: [PATCH 08/10] =?UTF-8?q?update:=20=E4=BC=98=E5=8C=96=200392.?= =?UTF-8?q?=E5=88=A4=E6=96=AD=E5=AD=90=E5=BA=8F=E5=88=97=20typescript=20?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0392.判断子序列.md | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/problems/0392.判断子序列.md b/problems/0392.判断子序列.md index f7863c94..8d1a0208 100644 --- a/problems/0392.判断子序列.md +++ b/problems/0392.判断子序列.md @@ -221,21 +221,19 @@ function isSubsequence(s: string, t: string): boolean { /** dp[i][j]: s的前i-1个,t的前j-1个,最长公共子序列的长度 */ - const sLen: number = s.length, - tLen: number = t.length; - const dp: number[][] = new Array(sLen + 1).fill(0) - .map(_ => new Array(tLen + 1).fill(0)); + const sLen = s.length + const tLen = t.length + const dp: number[][] = new Array(sLen + 1).fill(0).map(_ => new Array(tLen + 1).fill(0)) + for (let i = 1; i <= sLen; i++) { for (let j = 1; j <= tLen; j++) { - if (s[i - 1] === t[j - 1]) { - dp[i][j] = dp[i - 1][j - 1] + 1; - } else { - dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); - } + if (s[i - 1] === t[j - 1]) dp[i][j] = dp[i - 1][j - 1] + 1 + // 只需要取 j-2 的 dp 值即可,不用考虑 i-2 + else dp[i][j] = dp[i][j - 1] } } - return dp[sLen][tLen] === s.length; -}; + return dp[sLen][tLen] === s.length +} ``` ### Go: From 74417c7695011c3c49d702f17cde22dfbce7aef3 Mon Sep 17 00:00:00 2001 From: xin Date: Sun, 29 Oct 2023 17:43:18 +0800 Subject: [PATCH 09/10] =?UTF-8?q?add:=200392.=E5=88=A4=E6=96=AD=E5=AD=90?= =?UTF-8?q?=E5=BA=8F=E5=88=97=20typescript=20=E6=96=B0=E5=A2=9E=E6=BB=9A?= =?UTF-8?q?=E5=8A=A8=E6=95=B0=E7=BB=84=E8=A7=A3=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0392.判断子序列.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/problems/0392.判断子序列.md b/problems/0392.判断子序列.md index 8d1a0208..ebd567cb 100644 --- a/problems/0392.判断子序列.md +++ b/problems/0392.判断子序列.md @@ -216,6 +216,8 @@ const isSubsequence = (s, t) => { ### TypeScript: +> 二维数组 + ```typescript function isSubsequence(s: string, t: string): boolean { /** @@ -236,6 +238,31 @@ function isSubsequence(s: string, t: string): boolean { } ``` +> 滚动数组 +```typescript +function isSubsequence(s: string, t: string): boolean { + const sLen = s.length + const tLen = t.length + const dp: number[] = new Array(tLen + 1).fill(0) + + for (let i = 1; i <= sLen; i++) { + let prev: number = 0; + let temp: number = 0; + for (let j = 1; j <= tLen; j++) { + // 备份一下当前状态(经过上层迭代后的) + temp = dp[j] + // prev 相当于 dp[j-1](累加了上层的状态) + // 如果单纯 dp[j-1] 则不会包含上层状态 + if (s[i - 1] === t[j - 1]) dp[j] = prev + 1 + else dp[j] = dp[j - 1] + // 继续使用上一层状态更新参数用于当前层下一个状态 + prev = temp + } + } + return dp[tLen] === sLen +} +``` + ### Go: 二维DP: From 6323296d76b6807e0794f233a93dda9e786ec0fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A8=8B=E5=BA=8F=E5=91=98Carl?= Date: Sat, 4 Nov 2023 16:27:32 +0800 Subject: [PATCH 10/10] =?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 --- problems/0239.滑动窗口最大值.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/problems/0239.滑动窗口最大值.md b/problems/0239.滑动窗口最大值.md index dbd036ee..19ac1261 100644 --- a/problems/0239.滑动窗口最大值.md +++ b/problems/0239.滑动窗口最大值.md @@ -62,13 +62,9 @@ public: 每次窗口移动的时候,调用que.pop(滑动窗口中移除元素的数值),que.push(滑动窗口添加元素的数值),然后que.front()就返回我们要的最大值。 -这么个队列香不香,要是有现成的这种数据结构是不是更香了! +这么个队列香不香,要是有现成的这种数据结构是不是更香了! -**可惜了,没有! 我们需要自己实现这么个队列。** -> 其实有这种数据结构的,在C++中,可以使用可以使用multiset这种数据结构作为单调队列 -> + 多重集合(`multiset`) 用以有序地存储元素的容器。允许存在相等的元素。 -> -> 在遍历原数组的时候,只需要把窗口的头元素加入到multiset中,然后把窗口的尾元素删除即可。因为multiset是有序的,并且提供了*rbegin(),可以直接获取窗口最大值。 +其实在C++中,可以使用 multiset 来模拟这个过程,文末提供这个解法仅针对C++,以下讲解我们还是靠自己来实现这个单调队列。 然后再分析一下,队列里的元素一定是要排序的,而且要最大值放在出队口,要不然怎么知道最大值呢。 @@ -845,6 +841,10 @@ impl Solution { ### C++ 使用multiset作为单调队列 + +多重集合(`multiset`) 用以有序地存储元素的容器。允许存在相等的元素。 + +在遍历原数组的时候,只需要把窗口的头元素加入到multiset中,然后把窗口的尾元素删除即可。因为multiset是有序的,并且提供了*rbegin(),可以直接获取窗口最大值。 ```cpp class Solution { public: