From 23c24d357e73eed31a46b58bf9bbc55047bfd2b7 Mon Sep 17 00:00:00 2001 From: WanpengXu Date: Fri, 12 Apr 2024 21:17:30 +0800 Subject: [PATCH 01/81] =?UTF-8?q?fix:=20=E4=BF=AE=E6=AD=A3=200015.?= =?UTF-8?q?=E4=B8=89=E6=95=B0=E4=B9=8B=E5=92=8C.md=20=E4=B8=AD=E7=9A=84?= =?UTF-8?q?=E4=B8=A5=E9=87=8D=E8=A1=A8=E8=BF=B0=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0015.三数之和.md | 55 ++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/problems/0015.三数之和.md b/problems/0015.三数之和.md index bf165788..edd22ec1 100644 --- a/problems/0015.三数之和.md +++ b/problems/0015.三数之和.md @@ -50,36 +50,49 @@ ```CPP class Solution { public: + // 在一个数组中找到3个数形成的三元组,它们的和为0,不能重复使用(三数下标互不相同),且三元组不能重复。 + // 理论解法:a+b+c(存储)==0(检索) <=> c(存储)==0-(a+b)(检索) + // 实际解法:a+b+c(存储)==0(检索) <=> b(存储)==0-(a+c)(检索) vector> threeSum(vector& nums) { - vector> result; + // 本解法的内层循环一边存储一边检索,所以被存储的应该是b,而不是c + vector> res; sort(nums.begin(), nums.end()); - // 找出a + b + c = 0 - // a = nums[i], b = nums[j], c = -(a + b) + + // 如果只有正数,不可能形成和为0的三元组 + if (nums[0] > 0) + return res; + for (int i = 0; i < nums.size(); i++) { - // 排序之后如果第一个元素已经大于零,那么不可能凑成三元组 - if (nums[i] > 0) { - break; - } - if (i > 0 && nums[i] == nums[i - 1]) { //三元组元素a去重 + // [a, a, ...] 如果本轮a和上轮a相同,那么找到的b,c也是相同的,所以去重a + if (i > 0 && nums[i] == nums[i - 1]) continue; - } - unordered_set set; - for (int j = i + 1; j < nums.size(); j++) { - if (j > i + 2 - && nums[j] == nums[j-1] - && nums[j-1] == nums[j-2]) { // 三元组元素b去重 + + // 这个st的作用是存储b + unordered_set st; + + for (int k = i + 1; k < nums.size(); k++) { + // [(-2x), ..., (x), (x), x, x, x, ...] + // eg. [0, 0, 0] + // eg. [-4, 2, 2] + // eg. [(-4), -1, 0, 0, 1, (2), (2), {2}, {2}, 3, 3] + // 去重b=c时的b和c,即第三个x到最后一个x需要被跳过 + if (k > i + 2 && nums[k] == nums[k - 1] && nums[k - 1] == nums[k - 2]) continue; + + // a+b+c=0 <=> b=0-(a+c) + int target = 0 - (nums[i] + nums[k]); + if (st.find(target) != st.end()) { + res.push_back({nums[i], target, nums[k]}); // nums[k]成为c + // 内层循环中,a固定,如果find到了和上轮一样的b,那么c也就和上轮一样,所以去重b + st.erase(target); } - int c = 0 - (nums[i] + nums[j]); - if (set.find(c) != set.end()) { - result.push_back({nums[i], nums[j], c}); - set.erase(c);// 三元组元素c去重 - } else { - set.insert(nums[j]); + else { + st.insert(nums[k]); // nums[k]成为b } } } - return result; + + return res; } }; ``` From c71a9b00eb103a13e78c8ba3d807c758cde5a127 Mon Sep 17 00:00:00 2001 From: WanpengXu Date: Fri, 12 Apr 2024 22:14:08 +0800 Subject: [PATCH 02/81] =?UTF-8?q?fix:=20=E4=BF=AE=E6=AD=A3=200015.?= =?UTF-8?q?=E4=B8=89=E6=95=B0=E4=B9=8B=E5=92=8C.md=20=E4=B8=AD=E7=9A=84?= =?UTF-8?q?=E4=B8=A5=E9=87=8D=E8=A1=A8=E8=BF=B0=E9=94=99=E8=AF=AF=EF=BC=88?= =?UTF-8?q?update:=20=E7=BB=9F=E4=B8=80=E5=8F=98=E9=87=8F=E5=90=8D?= =?UTF-8?q?=EF=BC=8C=E5=9B=9E=E9=80=80=E5=8E=BB=E9=87=8D=E9=80=BB=E8=BE=91?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0015.三数之和.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/problems/0015.三数之和.md b/problems/0015.三数之和.md index edd22ec1..0d47bf48 100644 --- a/problems/0015.三数之和.md +++ b/problems/0015.三数之和.md @@ -55,20 +55,20 @@ public: // 实际解法:a+b+c(存储)==0(检索) <=> b(存储)==0-(a+c)(检索) vector> threeSum(vector& nums) { // 本解法的内层循环一边存储一边检索,所以被存储的应该是b,而不是c - vector> res; + vector> result; sort(nums.begin(), nums.end()); - - // 如果只有正数,不可能形成和为0的三元组 - if (nums[0] > 0) - return res; for (int i = 0; i < nums.size(); i++) { + // 如果a是正数,a 0) + break; + // [a, a, ...] 如果本轮a和上轮a相同,那么找到的b,c也是相同的,所以去重a if (i > 0 && nums[i] == nums[i - 1]) continue; - // 这个st的作用是存储b - unordered_set st; + // 这个set的作用是存储b + unordered_set set; for (int k = i + 1; k < nums.size(); k++) { // [(-2x), ..., (x), (x), x, x, x, ...] @@ -81,18 +81,18 @@ public: // a+b+c=0 <=> b=0-(a+c) int target = 0 - (nums[i] + nums[k]); - if (st.find(target) != st.end()) { - res.push_back({nums[i], target, nums[k]}); // nums[k]成为c + if (set.find(target) != set.end()) { + result.push_back({nums[i], target, nums[k]}); // nums[k]成为c // 内层循环中,a固定,如果find到了和上轮一样的b,那么c也就和上轮一样,所以去重b - st.erase(target); + set.erase(target); } else { - st.insert(nums[k]); // nums[k]成为b + set.insert(nums[k]); // nums[k]成为b } } } - return res; + return result; } }; ``` From a4cafe0ce750c44f327a97a9811ff0b2d2c49979 Mon Sep 17 00:00:00 2001 From: Lane Zhang Date: Wed, 16 Oct 2024 11:25:49 +0800 Subject: [PATCH 03/81] =?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 04/81] =?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 05/81] =?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 06/81] =?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 07/81] =?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 08/81] =?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 09/81] =?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 10/81] =?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 11/81] =?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 12/81] =?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 13/81] 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 14/81] =?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 15/81] =?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 16/81] =?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 82468b6f2ae5e399306e3deedb0af540671b5417 Mon Sep 17 00:00:00 2001 From: markwang Date: Tue, 22 Oct 2024 11:31:15 +0800 Subject: [PATCH 17/81] =?UTF-8?q?583.=E4=B8=A4=E4=B8=AA=E5=AD=97=E7=AC=A6?= =?UTF-8?q?=E4=B8=B2=E7=9A=84=E5=88=A0=E9=99=A4=E6=93=8D=E4=BD=9C=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0Go=E5=8A=A8=E6=80=81=E8=A7=84=E5=88=92=E4=BA=8C?= =?UTF-8?q?=E8=A7=A3=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../0583.两个字符串的删除操作.md | 33 ++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/problems/0583.两个字符串的删除操作.md b/problems/0583.两个字符串的删除操作.md index 14a55631..57bd3abe 100644 --- a/problems/0583.两个字符串的删除操作.md +++ b/problems/0583.两个字符串的删除操作.md @@ -33,7 +33,7 @@ dp[i][j]:以i-1为结尾的字符串word1,和以j-1位结尾的字符串word2,想要达到相等,所需要删除元素的最少次数。 -这里dp数组的定义有点点绕,大家要撸清思路。 +这里dp数组的定义有点点绕,大家要理清思路。 2. 确定递推公式 @@ -255,6 +255,8 @@ class Solution(object): ``` ### Go: +动态规划一 + ```go func minDistance(word1 string, word2 string) int { dp := make([][]int, len(word1)+1) @@ -287,6 +289,35 @@ func min(a, b int) int { return b } ``` + +动态规划二 + +```go +func minDistance(word1 string, word2 string) int { + dp := make([][]int, len(word1) + 1) + for i := range dp { + dp[i] = make([]int, len(word2) + 1) + } + for i := 1; i <= len(word1); i++ { + for j := 1; j <= len(word2); j++ { + if word1[i-1] == word2[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 len(word1) + len(word2) - dp[len(word1)][len(word2)] * 2 +} + +func max(x, y int) int { + if x > y { + return x + } + return y +} +``` + ### Javascript: ```javascript From dcbd5b4674c763dd2e156318cee383a79861f954 Mon Sep 17 00:00:00 2001 From: Lane Zhang Date: Wed, 23 Oct 2024 10:07:56 +0800 Subject: [PATCH 18/81] =?UTF-8?q?=E4=BA=8C=E5=8F=89=E6=A0=91=E7=9A=84?= =?UTF-8?q?=E9=80=92=E5=BD=92=E9=81=8D=E5=8E=86.md=20=E5=8E=BB=E6=8E=89=20?= =?UTF-8?q?Python=20=E7=89=88=E6=9C=AC=E4=B8=AD=E6=97=A0=E7=94=A8=E7=9A=84?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/二叉树的迭代遍历.md | 4 +--- problems/栈与队列总结.md | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/problems/二叉树的迭代遍历.md b/problems/二叉树的迭代遍历.md index 5f59c388..ba63d06b 100644 --- a/problems/二叉树的迭代遍历.md +++ b/problems/二叉树的迭代遍历.md @@ -262,8 +262,6 @@ class Solution: # 中序遍历-迭代-LC94_二叉树的中序遍历 class Solution: def inorderTraversal(self, root: TreeNode) -> List[int]: - if not root: - return [] stack = [] # 不能提前将root结点加入stack中 result = [] cur = root @@ -280,7 +278,7 @@ class Solution: cur = cur.right return result ``` - ```python +```python # 后序遍历-迭代-LC145_二叉树的后序遍历 class Solution: diff --git a/problems/栈与队列总结.md b/problems/栈与队列总结.md index 113f4a06..df022c77 100644 --- a/problems/栈与队列总结.md +++ b/problems/栈与队列总结.md @@ -107,7 +107,7 @@ cd a/b/c/../../ 设计单调队列的时候,pop,和push操作要保持如下规则: 1. pop(value):如果窗口移除的元素value等于单调队列的出口元素,那么队列弹出元素,否则不用任何操作 -2. push(value):如果push的元素value大于入口元素的数值,那么就将队列出口的元素弹出,直到push元素的数值小于等于队列入口元素的数值为止 +2. push(value):如果push的元素value大于入口元素的数值,那么就将队列入口的元素弹出,直到push元素的数值小于等于队列入口元素的数值为止 保持如上规则,每次窗口移动的时候,只要问que.front()就可以返回当前窗口的最大值。 From a36358e06868764fab05b2821497991aded21256 Mon Sep 17 00:00:00 2001 From: Lane Zhang Date: Wed, 23 Oct 2024 10:22:58 +0800 Subject: [PATCH 19/81] =?UTF-8?q?=E4=BA=8C=E5=8F=89=E6=A0=91=E7=9A=84?= =?UTF-8?q?=E8=BF=AD=E4=BB=A3=E9=81=8D=E5=8E=86.md=20=E5=8A=A0=E5=85=A5=20?= =?UTF-8?q?Python=20=E7=89=88=E6=9C=AC=E7=9A=84=E5=90=8E=E5=BA=8F=E9=81=8D?= =?UTF-8?q?=E5=8E=86=E6=96=B0=E8=A7=A3=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/二叉树的迭代遍历.md | 38 ++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/problems/二叉树的迭代遍历.md b/problems/二叉树的迭代遍历.md index 5f59c388..00d24692 100644 --- a/problems/二叉树的迭代遍历.md +++ b/problems/二叉树的迭代遍历.md @@ -303,6 +303,44 @@ class Solution: return result[::-1] ``` +#### Python 后序遍历的迭代新解法: +* 本解法不同于前文介绍的`逆转前序遍历调整后的结果`,而是采用了对每个结点直接处理。 + +```python +class Solution: + def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]: + values = [] + stack = [] + popped_nodes = set() # 记录值已经被收割了的 nodes + current = root + + while current or stack: + if current: # 一次处理完一个结点和他的左右儿子结点,不处理孙子结点,孙子结点由左右儿子等会分别处理。 + stack.append(current) # 入栈自己 + + if current.right: + stack.append(current.right) # 入栈右儿子 + + if current.left: # 因为栈是后进先出,后序是‘左右中’,所以后加左儿子 + stack.append(current.left) # 入栈左儿子 + + current = None # 会导致后面A处出栈 + continue + + node = stack.pop() # A处,出的是左儿子,如果无左儿子,出的就是右儿子,如果连右儿子也没有,出的就是自己了。 + + # 如果 node 是叶子结点,就可以收割了;如果左右儿子都已经被收割了,也可以收割 + if (node.left is None or node.left in popped_nodes) and \ + (node.right is None or node.right in popped_nodes): + popped_nodes.add(node) + values.append(node.val) + continue + + current = node # 不符合收割条件,说明 node 下还有未入栈的儿子,就去入栈 + + return values +``` + ### Go: > 迭代法前序遍历 From bf540436f290e509fa8ae5d77cb75f250c154866 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lane=20Zhang=20=28=E5=BC=A0=E5=81=A5=29?= Date: Wed, 23 Oct 2024 10:33:48 +0800 Subject: [PATCH 20/81] =?UTF-8?q?Update=20=E4=BA=8C=E5=8F=89=E6=A0=91?= =?UTF-8?q?=E7=9A=84=E8=BF=AD=E4=BB=A3=E9=81=8D=E5=8E=86.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/二叉树的迭代遍历.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/problems/二叉树的迭代遍历.md b/problems/二叉树的迭代遍历.md index 00d24692..3b4b30fb 100644 --- a/problems/二叉树的迭代遍历.md +++ b/problems/二叉树的迭代遍历.md @@ -240,14 +240,14 @@ class Solution { # 前序遍历-迭代-LC144_二叉树的前序遍历 class Solution: def preorderTraversal(self, root: TreeNode) -> List[int]: - # 根结点为空则返回空列表 + # 根节点为空则返回空列表 if not root: return [] stack = [root] result = [] while stack: node = stack.pop() - # 中结点先处理 + # 中节点先处理 result.append(node.val) # 右孩子先入栈 if node.right: @@ -264,19 +264,19 @@ class Solution: def inorderTraversal(self, root: TreeNode) -> List[int]: if not root: return [] - stack = [] # 不能提前将root结点加入stack中 + stack = [] # 不能提前将root节点加入stack中 result = [] cur = root while cur or stack: - # 先迭代访问最底层的左子树结点 + # 先迭代访问最底层的左子树节点 if cur: stack.append(cur) cur = cur.left - # 到达最左结点后处理栈顶结点 + # 到达最左节点后处理栈顶节点 else: cur = stack.pop() result.append(cur.val) - # 取栈顶元素右结点 + # 取栈顶元素右节点 cur = cur.right return result ``` @@ -291,7 +291,7 @@ class Solution: result = [] while stack: node = stack.pop() - # 中结点先处理 + # 中节点先处理 result.append(node.val) # 左孩子先入栈 if node.left: @@ -304,7 +304,7 @@ class Solution: ``` #### Python 后序遍历的迭代新解法: -* 本解法不同于前文介绍的`逆转前序遍历调整后的结果`,而是采用了对每个结点直接处理。 +* 本解法不同于前文介绍的`逆转前序遍历调整后的结果`,而是采用了对每个节点直接处理。 ```python class Solution: @@ -315,7 +315,7 @@ class Solution: current = root while current or stack: - if current: # 一次处理完一个结点和他的左右儿子结点,不处理孙子结点,孙子结点由左右儿子等会分别处理。 + if current: # 一次处理完一个节点和他的左右儿子节点,不处理孙子节点,孙子节点由左右儿子等会分别处理。 stack.append(current) # 入栈自己 if current.right: @@ -329,7 +329,7 @@ class Solution: node = stack.pop() # A处,出的是左儿子,如果无左儿子,出的就是右儿子,如果连右儿子也没有,出的就是自己了。 - # 如果 node 是叶子结点,就可以收割了;如果左右儿子都已经被收割了,也可以收割 + # 如果 node 是叶子节点,就可以收割了;如果左右儿子都已经被收割了,也可以收割 if (node.left is None or node.left in popped_nodes) and \ (node.right is None or node.right in popped_nodes): popped_nodes.add(node) From 8b7027f2b7e911f4474c9c4c545c3a031639e16f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lane=20Zhang=20=28=E5=BC=A0=E5=81=A5=29?= Date: Wed, 23 Oct 2024 12:30:11 +0800 Subject: [PATCH 21/81] =?UTF-8?q?Update=20=E4=BA=8C=E5=8F=89=E6=A0=91?= =?UTF-8?q?=E7=9A=84=E8=BF=AD=E4=BB=A3=E9=81=8D=E5=8E=86.md=20=E8=B0=83?= =?UTF-8?q?=E6=95=B4=E6=B3=A8=E9=87=8A=E5=86=85=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/二叉树的迭代遍历.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/problems/二叉树的迭代遍历.md b/problems/二叉树的迭代遍历.md index 3b4b30fb..79b54929 100644 --- a/problems/二叉树的迭代遍历.md +++ b/problems/二叉树的迭代遍历.md @@ -304,14 +304,14 @@ class Solution: ``` #### Python 后序遍历的迭代新解法: -* 本解法不同于前文介绍的`逆转前序遍历调整后的结果`,而是采用了对每个节点直接处理。 +* 本解法不同于前文介绍的`逆转前序遍历调整后的结果`,而是采用了对每个节点直接处理。这个实现方法在面试中不容易写出来,在下一节,我将改造本代码,奉上代码更简洁、更套路化、更容易实现的统一方法。 ```python class Solution: def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]: values = [] stack = [] - popped_nodes = set() # 记录值已经被收割了的 nodes + popped_nodes = set() # 记录值已经被收割了的 nodes,这是关键,已经被收割的节点还在树中,还会被访问到,但逻辑上已经等同于 null 节点。 current = root while current or stack: From b8a4613c53be3d295cf8d56993284777927ca9f1 Mon Sep 17 00:00:00 2001 From: Lane Zhang Date: Wed, 23 Oct 2024 14:14:42 +0800 Subject: [PATCH 22/81] =?UTF-8?q?=E4=BA=8C=E5=8F=89=E6=A0=91=E7=9A=84?= =?UTF-8?q?=E7=BB=9F=E4=B8=80=E8=BF=AD=E4=BB=A3=E6=B3=95.md=20=E5=8A=A0?= =?UTF-8?q?=E5=85=A5"Set=E6=A0=87=E8=AE=B0=E6=B3=95"=E5=92=8C=E7=9B=B8?= =?UTF-8?q?=E5=85=B3Python=E4=BB=A3=E7=A0=81=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/二叉树的统一迭代法.md | 69 +++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 4 deletions(-) diff --git a/problems/二叉树的统一迭代法.md b/problems/二叉树的统一迭代法.md index 13c50737..a1ac9dd2 100644 --- a/problems/二叉树的统一迭代法.md +++ b/problems/二叉树的统一迭代法.md @@ -27,7 +27,12 @@ **那我们就将访问的节点放入栈中,把要处理的节点也放入栈中但是要做标记。** -如何标记呢,**就是要处理的节点放入栈之后,紧接着放入一个空指针作为标记。** 这种方法也可以叫做标记法。 +如何标记呢? + +* 方法一:**就是要处理的节点放入栈之后,紧接着放入一个空指针作为标记。** 这种方法可以叫做`空指针标记法`。 + +* 方法二:**当一个节点被`pop()`后,把该节点放入一个`Set`中,表示该节点被处理过了,下次再处理这个节点时,直接收割。** +这种方法可以叫做`Set标记法`,样例代码见下文`Python Set标记法`。 方法二更容易理解,在面试中更容易写出来。 ### 迭代法中序遍历 @@ -234,7 +239,7 @@ class Solution { ### Python: -迭代法前序遍历: +> 迭代法前序遍历(空指针标记法): ```python class Solution: def preorderTraversal(self, root: TreeNode) -> List[int]: @@ -257,7 +262,7 @@ class Solution: return result ``` -迭代法中序遍历: +> 迭代法中序遍历(空指针标记法): ```python class Solution: def inorderTraversal(self, root: TreeNode) -> List[int]: @@ -282,7 +287,7 @@ class Solution: return result ``` -迭代法后序遍历: +> 迭代法后序遍历(空指针标记法): ```python class Solution: def postorderTraversal(self, root: TreeNode) -> List[int]: @@ -306,6 +311,62 @@ class Solution: return result ``` +> 中序遍历,统一迭代(Set标记法): +```python +class Solution: + def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]: + values = [] + stack = [] if root is None else [root] + popped_nodes = set() # 用于记录一个节点是否被 pop() 过 + + while stack: + node = stack.pop() + # 说明节点是之前被pop过又被加回来,现在又要出栈,就可以直接收割了, + # 因为节点的左右儿子已经按次序入栈,节点的使命已经完成。 + if node in popped_nodes: + values.append(node.val) + continue + + popped_nodes.add(node) # 记录第一次出栈,第一次出栈的目的是为了把左右儿子和自己按次序入栈 + + if node.right: # 中序遍历是'左中右',右儿子最先入栈,最后出栈 + stack.append(node.right) + + stack.append(node) # 把自己加回到栈中,位置居中 + + if node.left: + stack.append(node.left) # 左儿子最后入栈,最先出栈 + + return values +``` + +> 后序遍历,统一迭代(Set标记法): +```python +class Solution: + def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]: + values = [] + stack = [] if root is None else [root] + popped_nodes = set() # 用于记录一个节点是否被 pop() 过 + + while stack: + node = stack.pop() + # 说明节点是之前被pop过又被加回来,现在又要出栈,就可以直接收割了, + # 因为节点的左右儿子已经按次序入栈,节点的使命已经完成。 + if node in popped_nodes: + values.append(node.val) + continue + + popped_nodes.add(node) # 记录第一次出栈,第一次出栈的目的是为了把左右儿子和自己按次序入栈 + + stack.append(node) # 后序遍历是'左右中',节点自己最先入栈,最后出栈 + + if node.right: + stack.append(node.right) # 右儿子位置居中 + + if node.left: + stack.append(node.left) # 左儿子最后入栈,最先出栈 +``` + ### Go: > 前序遍历统一迭代法 From 6eb35a973796c440fde91ae5ef66fe75c1dfb426 Mon Sep 17 00:00:00 2001 From: markwang Date: Wed, 23 Oct 2024 16:19:36 +0800 Subject: [PATCH 23/81] =?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 24/81] =?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 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 25/81] =?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 26/81] =?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 27/81] =?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 28/81] =?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 29/81] =?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 a8ac9f9ae075115972ee5bf578890eb4198e4e2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lane=20Zhang=20=28=E5=BC=A0=E5=81=A5=29?= Date: Thu, 24 Oct 2024 09:15:07 +0800 Subject: [PATCH 30/81] =?UTF-8?q?Update=20=E4=BA=8C=E5=8F=89=E6=A0=91?= =?UTF-8?q?=E7=9A=84=E7=BB=9F=E4=B8=80=E8=BF=AD=E4=BB=A3=E6=B3=95.md=20?= =?UTF-8?q?=E5=BE=AE=E8=B0=83=20stack=20=E8=B5=8B=E5=80=BC=E8=AF=AD?= =?UTF-8?q?=E5=8F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/二叉树的统一迭代法.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/problems/二叉树的统一迭代法.md b/problems/二叉树的统一迭代法.md index a1ac9dd2..3a74a932 100644 --- a/problems/二叉树的统一迭代法.md +++ b/problems/二叉树的统一迭代法.md @@ -316,7 +316,7 @@ class Solution: class Solution: def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]: values = [] - stack = [] if root is None else [root] + stack = [root] if root else [] popped_nodes = set() # 用于记录一个节点是否被 pop() 过 while stack: @@ -345,7 +345,7 @@ class Solution: class Solution: def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]: values = [] - stack = [] if root is None else [root] + stack = [root] if root else [] popped_nodes = set() # 用于记录一个节点是否被 pop() 过 while stack: From 775accb7fdb783c2ec253c59c4e387c852a22166 Mon Sep 17 00:00:00 2001 From: Lane Zhang Date: Thu, 24 Oct 2024 10:41:30 +0800 Subject: [PATCH 31/81] =?UTF-8?q?0226.=E7=BF=BB=E8=BD=AC=E4=BA=8C=E5=8F=89?= =?UTF-8?q?=E6=A0=91.md=20=E4=BF=AE=E6=AD=A3=E5=87=A0=E5=A4=84=20Python=20?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E4=B8=8D=E4=B8=A5=E8=B0=A8=E8=AF=B4=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0226.翻转二叉树.md | 40 ++++++++++++++------------------ 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/problems/0226.翻转二叉树.md b/problems/0226.翻转二叉树.md index e501b298..285f971a 100644 --- a/problems/0226.翻转二叉树.md +++ b/problems/0226.翻转二叉树.md @@ -81,7 +81,7 @@ if (root == NULL) return root; 3. 确定单层递归的逻辑 -因为是先前序遍历,所以先进行交换左右孩子节点,然后反转左子树,反转右子树。 +因为是前序遍历,所以先进行交换左右孩子节点,然后反转左子树,反转右子树。 ```cpp swap(root->left, root->right); @@ -348,14 +348,13 @@ class Solution: while stack: node = stack.pop() node.left, node.right = node.right, node.left + if node.right: + stack.append(node.right) if node.left: stack.append(node.left) - if node.right: - stack.append(node.right) return root ``` - 递归法:中序遍历: ```python # Definition for a binary tree node. @@ -374,7 +373,7 @@ class Solution: return root ``` -迭代法:中序遍历: +迭代法,伪中序遍历(结果是对的,看起来像是中序遍历,实际上它是前序遍历,只不过把中间节点处理逻辑放到了中间。还是要用'统一写法'才是真正的中序遍历): ```python # Definition for a binary tree node. # class TreeNode: @@ -386,18 +385,17 @@ class Solution: def invertTree(self, root: TreeNode) -> TreeNode: if not root: return None - stack = [root] + stack = [root] while stack: - node = stack.pop() - if node.left: - stack.append(node.left) - node.left, node.right = node.right, node.left - if node.left: - stack.append(node.left) + node = stack.pop() + if node.right: + stack.append(node.right) + node.left, node.right = node.right, node.left # 放到中间,依然是前序遍历 + if node.right: + stack.append(node.right) return root ``` - 递归法:后序遍历: ```python # Definition for a binary tree node. @@ -416,7 +414,7 @@ class Solution: return root ``` -迭代法:后序遍历: +迭代法,伪后序遍历(结果是对的,看起来像是后序遍历,实际上它是前序遍历,只不过把中间节点处理逻辑放到了最后。还是要用'统一写法'才是真正的后序遍历): ```python # Definition for a binary tree node. # class TreeNode: @@ -427,23 +425,19 @@ class Solution: class Solution: def invertTree(self, root: TreeNode) -> TreeNode: if not root: - return None - stack = [root] + return None + stack = [root] while stack: - node = stack.pop() + node = stack.pop() + if node.right: + stack.append(node.right) if node.left: stack.append(node.left) - if node.right: - stack.append(node.right) node.left, node.right = node.right, node.left return root ``` - - - - 迭代法:广度优先遍历(层序遍历): ```python # Definition for a binary tree node. From 2ddf04ff1432c5a3f0fdf81061913a5c7fcccd47 Mon Sep 17 00:00:00 2001 From: zhangrunzhe Date: Thu, 24 Oct 2024 18:04:48 +0800 Subject: [PATCH 32/81] =?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 33/81] 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 34/81] 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 55963190f82417db91a09f6f8a0a9fa080e87059 Mon Sep 17 00:00:00 2001 From: htzhu Date: Sat, 26 Oct 2024 21:45:08 -0700 Subject: [PATCH 35/81] =?UTF-8?q?Update=200738.=E5=8D=95=E8=B0=83=E9=80=92?= =?UTF-8?q?=E5=A2=9E=E7=9A=84=E6=95=B0=E5=AD=97.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Python代码里大写的N会报错,把N改为了小写n。 --- problems/0738.单调递增的数字.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/problems/0738.单调递增的数字.md b/problems/0738.单调递增的数字.md index 3d46d5ad..be4411dd 100644 --- a/problems/0738.单调递增的数字.md +++ b/problems/0738.单调递增的数字.md @@ -190,9 +190,9 @@ class Solution: 贪心(版本一) ```python class Solution: - def monotoneIncreasingDigits(self, N: int) -> int: + def monotoneIncreasingDigits(self, n: int) -> int: # 将整数转换为字符串 - strNum = str(N) + strNum = str(n) # flag用来标记赋值9从哪里开始 # 设置为字符串长度,为了防止第二个for循环在flag没有被赋值的情况下执行 flag = len(strNum) @@ -216,9 +216,9 @@ class Solution: 贪心(版本二) ```python class Solution: - def monotoneIncreasingDigits(self, N: int) -> int: + def monotoneIncreasingDigits(self, n: int) -> int: # 将整数转换为字符串 - strNum = list(str(N)) + strNum = list(str(n)) # 从右往左遍历字符串 for i in range(len(strNum) - 1, 0, -1): @@ -238,9 +238,9 @@ class Solution: ```python class Solution: - def monotoneIncreasingDigits(self, N: int) -> int: + def monotoneIncreasingDigits(self, n: int) -> int: # 将整数转换为字符串 - strNum = list(str(N)) + strNum = list(str(n)) # 从右往左遍历字符串 for i in range(len(strNum) - 1, 0, -1): @@ -258,8 +258,8 @@ class Solution: ```python class Solution: - def monotoneIncreasingDigits(self, N: int) -> int: - strNum = str(N) + def monotoneIncreasingDigits(self, n: int) -> int: + strNum = str(n) for i in range(len(strNum) - 1, 0, -1): # 如果当前字符比前一个字符小,说明需要修改前一个字符 if strNum[i - 1] > strNum[i]: @@ -272,12 +272,12 @@ class Solution: ``` ### Go ```go -func monotoneIncreasingDigits(N int) int { +func monotoneIncreasingDigits(n int) int { s := strconv.Itoa(N)//将数字转为字符串,方便使用下标 ss := []byte(s)//将字符串转为byte数组,方便更改。 n := len(ss) if n <= 1 { - return N + return n } for i := n-1; i > 0; i-- { if ss[i-1] > ss[i] { //前一个大于后一位,前一位减1,后面的全部置为9 From e317e8761ea063ea8cbe88474c9c8ef7a7e954dc Mon Sep 17 00:00:00 2001 From: markwang Date: Mon, 28 Oct 2024 10:15:08 +0800 Subject: [PATCH 36/81] =?UTF-8?q?84.=E6=9F=B1=E7=8A=B6=E5=9B=BE=E4=B8=AD?= =?UTF-8?q?=E6=9C=80=E5=A4=A7=E7=9A=84=E7=9F=A9=E5=BD=A2=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?Go=E8=A7=A3=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0084.柱状图中最大的矩形.md | 123 ++++++++++++++++++- 1 file changed, 122 insertions(+), 1 deletion(-) diff --git a/problems/0084.柱状图中最大的矩形.md b/problems/0084.柱状图中最大的矩形.md index c08a3045..5c6f4073 100644 --- a/problems/0084.柱状图中最大的矩形.md +++ b/problems/0084.柱状图中最大的矩形.md @@ -474,7 +474,128 @@ class Solution: ### Go: -> 单调栈 +暴力解法 + +```go +func largestRectangleArea(heights []int) int { + sum := 0 + for i := 0; i < len(heights); i++ { + left, right := i, i + for left >= 0 { + if heights[left] < heights[i] { + break + } + left-- + } + for right < len(heights) { + if heights[right] < heights[i] { + break + } + right++ + } + w := right - left - 1 + h := heights[i] + sum = max(sum, w * h) + } + return sum +} + +func max(x, y int) int { + if x > y { + return x + } + return y +} +``` + +双指针解法 + +```go +func largestRectangleArea(heights []int) int { + size := len(heights) + minLeftIndex := make([]int, size) + minRightIndex := make([]int, size) + + // 记录每个柱子 左边第一个小于该柱子的下标 + minLeftIndex[0] = -1 // 注意这里初始化,防止下面while死循环 + for i := 1; i < size; i++ { + t := i - 1 + // 这里不是用if,而是不断向左寻找的过程 + for t >= 0 && heights[t] >= heights[i] { + t = minLeftIndex[t] + } + minLeftIndex[i] = t + } + // 记录每个柱子 右边第一个小于该柱子的下标 + minRightIndex[size - 1] = size; // 注意这里初始化,防止下面while死循环 + for i := size - 2; i >= 0; i-- { + t := i + 1 + // 这里不是用if,而是不断向右寻找的过程 + for t < size && heights[t] >= heights[i] { + t = minRightIndex[t] + } + minRightIndex[i] = t + } + // 求和 + result := 0 + for i := 0; i < size; i++ { + sum := heights[i] * (minRightIndex[i] - minLeftIndex[i] - 1) + result = max(sum, result) + } + return result +} + +func max(x, y int) int { + if x > y { + return x + } + return y +} +``` + +单调栈 + +```go +func largestRectangleArea(heights []int) int { + result := 0 + heights = append([]int{0}, heights...) // 数组头部加入元素0 + heights = append(heights, 0) // 数组尾部加入元素0 + st := []int{0} + + // 第一个元素已经入栈,从下标1开始 + for i := 1; i < len(heights); i++ { + if heights[i] > heights[st[len(st)-1]] { + st = append(st, i) + } else if heights[i] == heights[st[len(st)-1]] { + st = st[:len(st)-1] + st = append(st, i) + } else { + for len(st) > 0 && heights[i] < heights[st[len(st)-1]] { + mid := st[len(st)-1] + st = st[:len(st)-1] + if len(st) > 0 { + left := st[len(st)-1] + right := i + w := right - left - 1 + h := heights[mid] + result = max(result, w * h) + } + } + st = append(st, i) + } + } + return result +} + +func max(x, y int) int { + if x > y { + return x + } + return y +} +``` + +单调栈精简 ```go func largestRectangleArea(heights []int) int { From abefd5840b64b3f82148bf383499bd854f20e42d Mon Sep 17 00:00:00 2001 From: zhoutianyi Date: Sun, 27 Oct 2024 23:39:32 -0400 Subject: [PATCH 37/81] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=9B=AE=E6=A0=87?= =?UTF-8?q?=E5=92=8C=20go=20=E5=9B=9E=E6=BA=AF=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0494.目标和.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/problems/0494.目标和.md b/problems/0494.目标和.md index 08724609..09e77b12 100644 --- a/problems/0494.目标和.md +++ b/problems/0494.目标和.md @@ -706,6 +706,31 @@ class Solution: ``` ### Go +回溯法思路 +```go +func findTargetSumWays(nums []int, target int) int { + var result int + var backtracking func(nums []int, target int, index int, currentSum int) + + backtracking = func(nums []int, target int, index int, currentSum int) { + if index == len(nums) { + if currentSum == target { + result++ + } + return + } + + // 选择加上当前数字 + backtracking(nums, target, index+1, currentSum+nums[index]) + + // 选择减去当前数字 + backtracking(nums, target, index+1, currentSum-nums[index]) + } + + backtracking(nums, target, 0, 0) + return result +} +``` 二维dp ```go func findTargetSumWays(nums []int, target int) int { From 497bb7cbf358a4db63dcd32650513ae7e949bedd Mon Sep 17 00:00:00 2001 From: hui <760261797@qq.com> Date: Tue, 29 Oct 2024 16:40:27 +0800 Subject: [PATCH 38/81] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E7=AC=94=E8=AF=AF?= =?UTF-8?q?=EF=BC=8C=E6=95=B0=E7=BB=84=E4=B8=8E=E5=9B=BE=E7=89=87=E4=B8=8D?= =?UTF-8?q?=E4=B8=80=E8=87=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0376.摆动序列.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/problems/0376.摆动序列.md b/problems/0376.摆动序列.md index 9e6714ce..88b59ffc 100644 --- a/problems/0376.摆动序列.md +++ b/problems/0376.摆动序列.md @@ -72,7 +72,7 @@ #### 情况一:上下坡中有平坡 -例如 [1,2,2,2,1]这样的数组,如图: +例如 [1,2,2,2,2,1]这样的数组,如图: ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20230106170449.png) From 28de17ec3921f86376f493a781727e7589d26b73 Mon Sep 17 00:00:00 2001 From: Kuxry Date: Wed, 30 Oct 2024 09:54:39 +0900 Subject: [PATCH 39/81] =?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 40/81] =?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 41/81] =?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 b3c79d848410230687321964ee39f238fb9f030c Mon Sep 17 00:00:00 2001 From: donghuanjie Date: Thu, 31 Oct 2024 19:38:10 -0700 Subject: [PATCH 42/81] modified 707 code, move the ListNode class inside, reformat the code --- problems/0707.设计链表.md | 128 +++++++++++++++++----------------- 1 file changed, 63 insertions(+), 65 deletions(-) diff --git a/problems/0707.设计链表.md b/problems/0707.设计链表.md index 0cb2f2f2..ed1726d9 100644 --- a/problems/0707.设计链表.md +++ b/problems/0707.设计链表.md @@ -422,38 +422,38 @@ void myLinkedListFree(MyLinkedList* obj) { ```Java //单链表 -class ListNode { - int val; - ListNode next; - ListNode(){} - ListNode(int val) { - this.val=val; - } -} class MyLinkedList { + + class ListNode { + int val; + ListNode next; + ListNode(int val) { + this.val=val; + } + } //size存储链表元素的个数 - int size; - //虚拟头结点 - ListNode head; + private int size; + //注意这里记录的是虚拟头结点 + private ListNode head; //初始化链表 public MyLinkedList() { - size = 0; - head = new ListNode(0); + this.size = 0; + this.head = new ListNode(0); } - //获取第index个节点的数值,注意index是从0开始的,第0个节点就是头结点 + //获取第index个节点的数值,注意index是从0开始的,第0个节点就是虚拟头结点 public int get(int index) { //如果index非法,返回-1 if (index < 0 || index >= size) { return -1; } - ListNode currentNode = head; - //包含一个虚拟头节点,所以查找第 index+1 个节点 + ListNode cur = head; + //第0个节点是虚拟头节点,所以查找第 index+1 个节点 for (int i = 0; i <= index; i++) { - currentNode = currentNode.next; + cur = cur.next; } - return currentNode.val; + return cur.val; } public void addAtHead(int val) { @@ -473,7 +473,6 @@ class MyLinkedList { while (cur.next != null) { cur = cur.next; } - cur.next = newNode; size++; @@ -485,55 +484,53 @@ class MyLinkedList { // 如果 index 等于链表的长度,则说明是新插入的节点为链表的尾结点 // 如果 index 大于链表的长度,则返回空 public void addAtIndex(int index, int val) { - if (index > size) { + if (index < 0 || index > size) { return; } - if (index < 0) { - index = 0; - } - size++; + //找到要插入节点的前驱 - ListNode pred = head; + ListNode pre = head; for (int i = 0; i < index; i++) { - pred = pred.next; + pre = pre.next; } - ListNode toAdd = new ListNode(val); - toAdd.next = pred.next; - pred.next = toAdd; + ListNode newNode = new ListNode(val); + newNode.next = pre.next; + pre.next = newNode; + size++; } - //删除第index个节点 public void deleteAtIndex(int index) { if (index < 0 || index >= size) { return; } - size--; - //因为有虚拟头节点,所以不用对Index=0的情况进行特殊处理 - ListNode pred = head; + + //因为有虚拟头节点,所以不用对index=0的情况进行特殊处理 + ListNode pre = head; for (int i = 0; i < index ; i++) { - pred = pred.next; + pre = pre.next; } - pred.next = pred.next.next; + pre.next = pre.next.next; + size--; } } +``` +```Java //双链表 -class ListNode{ - int val; - ListNode next,prev; - ListNode() {}; - ListNode(int val){ - this.val = val; - } -} - - class MyLinkedList { + class ListNode{ + int val; + ListNode next, prev; + ListNode(int val){ + this.val = val; + } + } + //记录链表中元素的数量 - int size; + private int size; //记录链表的虚拟头结点和尾结点 - ListNode head,tail; + private ListNode head, tail; public MyLinkedList() { //初始化操作 @@ -541,25 +538,25 @@ class MyLinkedList { this.head = new ListNode(0); this.tail = new ListNode(0); //这一步非常关键,否则在加入头结点的操作中会出现null.next的错误!!! - head.next=tail; - tail.prev=head; + this.head.next = tail; + this.tail.prev = head; } public int get(int index) { //判断index是否有效 - if(index>=size){ + if(index < 0 || index >= size){ return -1; } - ListNode cur = this.head; + ListNode cur = head; //判断是哪一边遍历时间更短 if(index >= size / 2){ //tail开始 cur = tail; - for(int i=0; i< size-index; i++){ + for(int i = 0; i < size - index; i++){ cur = cur.prev; } }else{ - for(int i=0; i<= index; i++){ + for(int i = 0; i <= index; i++){ cur = cur.next; } } @@ -568,24 +565,23 @@ class MyLinkedList { public void addAtHead(int val) { //等价于在第0个元素前添加 - addAtIndex(0,val); + addAtIndex(0, val); } public void addAtTail(int val) { //等价于在最后一个元素(null)前添加 - addAtIndex(size,val); + addAtIndex(size, val); } public void addAtIndex(int index, int val) { - //index大于链表长度 - if(index>size){ + //判断index是否有效 + if(index < 0 || index > size){ return; } - size++; //找到前驱 - ListNode pre = this.head; - for(int i=0; i=size){ + //判断index是否有效 + if(index < 0 || index >= size){ return; } + //删除操作 - size--; - ListNode pre = this.head; - for(int i=0; i Date: Fri, 1 Nov 2024 14:15:14 +0800 Subject: [PATCH 43/81] =?UTF-8?q?992.=E6=8C=89=E5=A5=87=E5=81=B6=E6=8E=92?= =?UTF-8?q?=E5=BA=8F=E6=95=B0=E7=BB=84II=E6=9B=B4=E6=96=B0=E9=A2=98?= =?UTF-8?q?=E7=9B=AE=E6=8F=8F=E8=BF=B0=EF=BC=8C=E5=A2=9E=E5=8A=A0Go?= =?UTF-8?q?=E6=96=B9=E6=B3=95=E4=BA=8C=E5=92=8C=E6=96=B9=E6=B3=95=E4=B8=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0922.按奇偶排序数组II.md | 77 +++++++++++++++++------- 1 file changed, 54 insertions(+), 23 deletions(-) diff --git a/problems/0922.按奇偶排序数组II.md b/problems/0922.按奇偶排序数组II.md index 1ac6800c..28680dbf 100644 --- a/problems/0922.按奇偶排序数组II.md +++ b/problems/0922.按奇偶排序数组II.md @@ -11,9 +11,9 @@ [力扣题目链接](https://leetcode.cn/problems/sort-array-by-parity-ii/) -给定一个非负整数数组 A, A 中一半整数是奇数,一半整数是偶数。 +给定一个非负整数数组 nums, nums 中一半整数是奇数,一半整数是偶数。 -对数组进行排序,以便当 A[i] 为奇数时,i 也是奇数;当 A[i] 为偶数时, i 也是偶数。 +对数组进行排序,以便当 nums[i] 为奇数时,i 也是奇数;当 nums[i] 为偶数时, i 也是偶数。 你可以返回任何满足上述条件的数组作为答案。 @@ -35,17 +35,17 @@ ```CPP class Solution { public: - vector sortArrayByParityII(vector& A) { - vector even(A.size() / 2); // 初始化就确定数组大小,节省开销 - vector odd(A.size() / 2); - vector result(A.size()); + vector sortArrayByParityII(vector& nums) { + vector even(nums.size() / 2); // 初始化就确定数组大小,节省开销 + vector odd(nums.size() / 2); + vector result(nums.size()); int evenIndex = 0; int oddIndex = 0; int resultIndex = 0; - // 把A数组放进偶数数组,和奇数数组 - for (int i = 0; i < A.size(); i++) { - if (A[i] % 2 == 0) even[evenIndex++] = A[i]; - else odd[oddIndex++] = A[i]; + // 把nums数组放进偶数数组,和奇数数组 + for (int i = 0; i < nums.size(); i++) { + if (nums[i] % 2 == 0) even[evenIndex++] = nums[i]; + else odd[oddIndex++] = nums[i]; } // 把偶数数组,奇数数组分别放进result数组中 for (int i = 0; i < evenIndex; i++) { @@ -62,22 +62,22 @@ public: ### 方法二 -以上代码我是建了两个辅助数组,而且A数组还相当于遍历了两次,用辅助数组的好处就是思路清晰,优化一下就是不用这两个辅助树,代码如下: +以上代码我是建了两个辅助数组,而且nums数组还相当于遍历了两次,用辅助数组的好处就是思路清晰,优化一下就是不用这两个辅助数组,代码如下: ```CPP class Solution { public: - vector sortArrayByParityII(vector& A) { - vector result(A.size()); + vector sortArrayByParityII(vector& nums) { + vector result(nums.size()); int evenIndex = 0; // 偶数下标 int oddIndex = 1; // 奇数下标 - for (int i = 0; i < A.size(); i++) { - if (A[i] % 2 == 0) { - result[evenIndex] = A[i]; + for (int i = 0; i < nums.size(); i++) { + if (nums[i] % 2 == 0) { + result[evenIndex] = nums[i]; evenIndex += 2; } else { - result[oddIndex] = A[i]; + result[oddIndex] = nums[i]; oddIndex += 2; } } @@ -96,15 +96,15 @@ public: ```CPP class Solution { public: - vector sortArrayByParityII(vector& A) { + vector sortArrayByParityII(vector& nums) { int oddIndex = 1; - for (int i = 0; i < A.size(); i += 2) { - if (A[i] % 2 == 1) { // 在偶数位遇到了奇数 - while(A[oddIndex] % 2 != 0) oddIndex += 2; // 在奇数位找一个偶数 - swap(A[i], A[oddIndex]); // 替换 + for (int i = 0; i < nums.size(); i += 2) { + if (nums[i] % 2 == 1) { // 在偶数位遇到了奇数 + while(nums[oddIndex] % 2 != 0) oddIndex += 2; // 在奇数位找一个偶数 + swap(nums[i], nums[oddIndex]); // 替换 } } - return A; + return nums; } }; ``` @@ -253,6 +253,37 @@ func sortArrayByParityII(nums []int) []int { } return result; } + +// 方法二 +func sortArrayByParityII(nums []int) []int { + result := make([]int, len(nums)) + evenIndex := 0 // 偶数下标 + oddIndex := 1 // 奇数下标 + for _, v := range nums { + if v % 2 == 0 { + result[evenIndex] = v + evenIndex += 2 + } else { + result[oddIndex] = v + oddIndex += 2 + } + } + return result +} + +// 方法三 +func sortArrayByParityII(nums []int) []int { + oddIndex := 1 + for i := 0; i < len(nums); i += 2 { + if nums[i] % 2 == 1 { // 在偶数位遇到了奇数 + for nums[oddIndex] % 2 != 0 { + oddIndex += 2 // 在奇数位找一个偶数 + } + nums[i], nums[oddIndex] = nums[oddIndex], nums[i] + } + } + return nums +} ``` ### JavaScript From cc1cdb07db6598c98e804ad40af5fd958062a5d8 Mon Sep 17 00:00:00 2001 From: donghuanjie Date: Fri, 1 Nov 2024 01:12:34 -0700 Subject: [PATCH 44/81] add java recursion version of 203 --- problems/0203.移除链表元素.md | 31 +++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/problems/0203.移除链表元素.md b/problems/0203.移除链表元素.md index f6b5ef6d..d51895aa 100644 --- a/problems/0203.移除链表元素.md +++ b/problems/0203.移除链表元素.md @@ -337,6 +337,37 @@ public ListNode removeElements(ListNode head, int val) { ``` +递归 + +```java +/** + * 时间复杂度 O(n) + * 空间复杂度 O(n) + * @param head + * @param val + * @return + */ +class Solution { + public ListNode removeElements(ListNode head, int val) { + if (head == null) { + return head; + } + + // 假设 removeElements() 返回后面完整的已经去掉val节点的子链表 + // 在当前递归层用当前节点接住后面的子链表 + // 随后判断当前层的node是否需要被删除,如果是,就返回 + // 也可以先判断是否需要删除当前node,但是这样条件语句会比较不好想 + head.next = removeElements(head.next, val); + if (head.val == val) { + return head.next; + } + return head; + + // 实际上就是还原一个从尾部开始重新构建链表的过程 + } +} +``` + ### Python: ```python From 4c397b64f5f4aba97f9d9034182b83bd8a062db6 Mon Sep 17 00:00:00 2001 From: Lane Zhang Date: Mon, 4 Nov 2024 12:07:27 +0800 Subject: [PATCH 45/81] =?UTF-8?q?0450.=E5=88=A0=E9=99=A4=E4=BA=8C=E5=8F=89?= =?UTF-8?q?=E6=90=9C=E7=B4=A2=E6=A0=91=E4=B8=AD=E7=9A=84=E8=8A=82=E7=82=B9?= =?UTF-8?q?=20=E5=8A=A0=E5=85=A5Ruby=E9=80=92=E5=BD=92=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../0450.删除二叉搜索树中的节点.md | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/problems/0450.删除二叉搜索树中的节点.md b/problems/0450.删除二叉搜索树中的节点.md index f6057f44..7523c50a 100644 --- a/problems/0450.删除二叉搜索树中的节点.md +++ b/problems/0450.删除二叉搜索树中的节点.md @@ -801,6 +801,40 @@ impl Solution { } ``` +### Ruby +> 递归法: +```ruby +# @param {TreeNode} root +# @param {Integer} key +# @return {TreeNode} +def delete_node(root, key) + return nil if root.nil? + + right = root.right + left = root.left + + if root.val == key + return right if left.nil? + return left if right.nil? + + node = right + while node.left + node = node.left + end + node.left = left + + return right + end + + if root.val > key + root.left = delete_node(left, key) + else + root.right = delete_node(right, key) + end + + return root +end +```

From 8c389cb67328c37e3744ec52126aa6dcfec399b2 Mon Sep 17 00:00:00 2001 From: Lane Zhang Date: Tue, 5 Nov 2024 13:28:37 +0800 Subject: [PATCH 46/81] =?UTF-8?q?=E4=BA=8C=E5=8F=89=E6=A0=91=E7=9A=84?= =?UTF-8?q?=E7=BB=9F=E4=B8=80=E8=BF=AD=E4=BB=A3=E6=B3=95.md=20=E4=BD=BF?= =?UTF-8?q?=E7=94=A8"boolean=E6=A0=87=E8=AE=B0=E6=B3=95"=E5=B9=B6=E8=B0=83?= =?UTF-8?q?=E6=95=B4=E7=9B=B8=E5=85=B3Python=E4=BB=A3=E7=A0=81=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/二叉树的统一迭代法.md | 53 ++++++++++++------------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/problems/二叉树的统一迭代法.md b/problems/二叉树的统一迭代法.md index a1ac9dd2..412aec8c 100644 --- a/problems/二叉树的统一迭代法.md +++ b/problems/二叉树的统一迭代法.md @@ -31,8 +31,8 @@ * 方法一:**就是要处理的节点放入栈之后,紧接着放入一个空指针作为标记。** 这种方法可以叫做`空指针标记法`。 -* 方法二:**当一个节点被`pop()`后,把该节点放入一个`Set`中,表示该节点被处理过了,下次再处理这个节点时,直接收割。** -这种方法可以叫做`Set标记法`,样例代码见下文`Python Set标记法`。 方法二更容易理解,在面试中更容易写出来。 +* 方法二:**加一个 `boolean` 值跟随每个节点,`false` (默认值) 表示需要为该节点和它的左右儿子安排在栈中的位次,`true` 表示该节点的位次之前已经安排过了,可以收割节点了。** +这种方法可以叫做`boolean 标记法`,样例代码见下文`C++ 和 Python 的 boolean 标记法`。 这种方法更容易理解,在面试中更容易写出来。 ### 迭代法中序遍历 @@ -311,60 +311,59 @@ class Solution: return result ``` -> 中序遍历,统一迭代(Set标记法): +> 中序遍历,统一迭代(boolean 标记法): ```python class Solution: def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]: values = [] - stack = [] if root is None else [root] - popped_nodes = set() # 用于记录一个节点是否被 pop() 过 + stack = [(root, False)] if root else [] # 多加一个参数,False 为默认值,含义见下文 while stack: - node = stack.pop() - # 说明节点是之前被pop过又被加回来,现在又要出栈,就可以直接收割了, - # 因为节点的左右儿子已经按次序入栈,节点的使命已经完成。 - if node in popped_nodes: + node, visited = stack.pop() # 多加一个 visited 参数,使“迭代统一写法”成为一件简单的事 + + if visited: # visited 为 True,表示该节点和两个儿子的位次之前已经安排过了,现在可以收割节点了 values.append(node.val) continue - popped_nodes.add(node) # 记录第一次出栈,第一次出栈的目的是为了把左右儿子和自己按次序入栈 + # visited 当前为 False, 表示初次访问本节点,此次访问的目的是“把自己和两个儿子在栈中安排好位次”。 + # 中序遍历是'左中右',右儿子最先入栈,最后出栈。 + if node.right: + stack.append((node.right, False)) - if node.right: # 中序遍历是'左中右',右儿子最先入栈,最后出栈 - stack.append(node.right) - - stack.append(node) # 把自己加回到栈中,位置居中 + stack.append((node, True)) # 把自己加回到栈中,位置居中。同时,设置 visited 为 True,表示下次再访问本节点时,允许收割 if node.left: - stack.append(node.left) # 左儿子最后入栈,最先出栈 + stack.append((node.left, False)) # 左儿子最后入栈,最先出栈 return values ``` -> 后序遍历,统一迭代(Set标记法): +> 后序遍历,统一迭代(boolean 标记法): ```python class Solution: def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]: values = [] - stack = [] if root is None else [root] - popped_nodes = set() # 用于记录一个节点是否被 pop() 过 + stack = [(root, False)] if root else [] # 多加一个参数,False 为默认值,含义见下文 while stack: - node = stack.pop() - # 说明节点是之前被pop过又被加回来,现在又要出栈,就可以直接收割了, - # 因为节点的左右儿子已经按次序入栈,节点的使命已经完成。 - if node in popped_nodes: + node, visited = stack.pop() # 多加一个 visited 参数,使“迭代统一写法”成为一件简单的事 + + if visited: # visited 为 True,表示该节点和两个儿子位次之前已经安排过了,现在可以收割节点了 values.append(node.val) continue - popped_nodes.add(node) # 记录第一次出栈,第一次出栈的目的是为了把左右儿子和自己按次序入栈 - - stack.append(node) # 后序遍历是'左右中',节点自己最先入栈,最后出栈 + # visited 当前为 False, 表示初次访问本节点,此次访问的目的是“把自己和两个儿子在栈中安排好位次” + # 后序遍历是'左右中',节点自己最先入栈,最后出栈。 + # 同时,设置 visited 为 True,表示下次再访问本节点时,允许收割。 + stack.append((node, True)) if node.right: - stack.append(node.right) # 右儿子位置居中 + stack.append((node.right, False)) # 右儿子位置居中 if node.left: - stack.append(node.left) # 左儿子最后入栈,最先出栈 + stack.append((node.left, False)) # 左儿子最后入栈,最先出栈 + + return values ``` ### Go: From 6c2e5a0c5e6b0a6d520c80331c99c53d80ea3b1a Mon Sep 17 00:00:00 2001 From: Lane Zhang Date: Tue, 5 Nov 2024 14:42:35 +0800 Subject: [PATCH 47/81] =?UTF-8?q?=E4=BA=8C=E5=8F=89=E6=A0=91=E7=9A=84?= =?UTF-8?q?=E7=BB=9F=E4=B8=80=E8=BF=AD=E4=BB=A3=E6=B3=95.md=20=E4=B8=BA"bo?= =?UTF-8?q?olean=E6=A0=87=E8=AE=B0=E6=B3=95"=E5=8A=A0=E4=B8=8AC++=E7=9A=84?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/二叉树的统一迭代法.md | 79 ++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 2 deletions(-) diff --git a/problems/二叉树的统一迭代法.md b/problems/二叉树的统一迭代法.md index 412aec8c..037cf110 100644 --- a/problems/二叉树的统一迭代法.md +++ b/problems/二叉树的统一迭代法.md @@ -36,7 +36,7 @@ ### 迭代法中序遍历 -中序遍历代码如下:(详细注释) +> 中序遍历(空指针标记法)代码如下:(详细注释) ```CPP class Solution { @@ -75,6 +75,45 @@ public: 可以看出我们将访问的节点直接加入到栈中,但如果是处理的节点则后面放入一个空节点, 这样只有空节点弹出的时候,才将下一个节点放进结果集。 +> 中序遍历(boolean 标记法): +```c++ +class Solution { +public: + vector inorderTraversal(TreeNode* root) { + vector result; + stack> st; + if (root != nullptr) + st.push(make_pair(root, false)); // 多加一个参数,false 为默认值,含义见下文注释 + + while (!st.empty()) { + auto node = st.top().first; + auto visited = st.top().second; //多加一个 visited 参数,使“迭代统一写法”成为一件简单的事 + st.pop(); + + if (visited) { // visited 为 True,表示该节点和两个儿子位次之前已经安排过了,现在可以收割节点了 + result.push_back(node->val); + continue; + } + + // visited 当前为 false, 表示初次访问本节点,此次访问的目的是“把自己和两个儿子在栈中安排好位次”。 + + // 中序遍历是'左中右',右儿子最先入栈,最后出栈。 + if (node->right) + st.push(make_pair(node->right, false)); + + // 把自己加回到栈中,位置居中。 + // 同时,设置 visited 为 true,表示下次再访问本节点时,允许收割。 + st.push(make_pair(node, true)); + + if (node->left) + st.push(make_pair(node->left, false)); // 左儿子最后入栈,最先出栈 + } + + return result; + } +}; +``` + 此时我们再来看前序遍历代码。 ### 迭代法前序遍历 @@ -110,7 +149,7 @@ public: ### 迭代法后序遍历 -后续遍历代码如下: (**注意此时我们和中序遍历相比仅仅改变了两行代码的顺序**) +> 后续遍历代码如下: (**注意此时我们和中序遍历相比仅仅改变了两行代码的顺序**) ```CPP class Solution { @@ -141,6 +180,42 @@ public: }; ``` +> 迭代法后序遍历(boolean 标记法): +```c++ +class Solution { +public: + vector postorderTraversal(TreeNode* root) { + vector result; + stack> st; + if (root != nullptr) + st.push(make_pair(root, false)); // 多加一个参数,false 为默认值,含义见下文 + + while (!st.empty()) { + auto node = st.top().first; + auto visited = st.top().second; //多加一个 visited 参数,使“迭代统一写法”成为一件简单的事 + st.pop(); + + if (visited) { // visited 为 True,表示该节点和两个儿子位次之前已经安排过了,现在可以收割节点了 + result.push_back(node->val); + continue; + } + + // visited 当前为 false, 表示初次访问本节点,此次访问的目的是“把自己和两个儿子在栈中安排好位次”。 + // 后序遍历是'左右中',节点自己最先入栈,最后出栈。 + // 同时,设置 visited 为 true,表示下次再访问本节点时,允许收割。 + st.push(make_pair(node, true)); + + if (node->right) + st.push(make_pair(node->right, false)); // 右儿子位置居中 + + if (node->left) + st.push(make_pair(node->left, false)); // 左儿子最后入栈,最先出栈 + } + + return result; + } +}; +``` ## 总结 此时我们写出了统一风格的迭代法,不用在纠结于前序写出来了,中序写不出来的情况了。 From a4f9f01eb48b2a7d929154be69fd6cfe9dc9ea19 Mon Sep 17 00:00:00 2001 From: MAX <61301100+miaoxu404@users.noreply.github.com> Date: Tue, 5 Nov 2024 20:52:38 -0700 Subject: [PATCH 48/81] =?UTF-8?q?Update=200101.=E5=AD=A4=E5=B2=9B=E7=9A=84?= =?UTF-8?q?=E6=80=BB=E9=9D=A2=E7=A7=AF.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 对101.孤岛的总面积的python解法深搜版的补充,以及对广搜版的部分修改 --- problems/kamacoder/0101.孤岛的总面积.md | 67 +++++++++++++++++-- 1 file changed, 60 insertions(+), 7 deletions(-) diff --git a/problems/kamacoder/0101.孤岛的总面积.md b/problems/kamacoder/0101.孤岛的总面积.md index 006484de..fb2eb747 100644 --- a/problems/kamacoder/0101.孤岛的总面积.md +++ b/problems/kamacoder/0101.孤岛的总面积.md @@ -257,14 +257,62 @@ public class Main { ### Python +#### 深搜版 +```python +position = [[1, 0], [0, 1], [-1, 0], [0, -1]] +count = 0 + +def dfs(grid, x, y): + global count + grid[x][y] = 0 + count += 1 + for i, j in position: + next_x = x + i + next_y = y + j + if next_x < 0 or next_y < 0 or next_x >= len(grid) or next_y >= len(grid[0]): + continue + if grid[next_x][next_y] == 1: + dfs(grid, next_x, next_y) + +n, m = map(int, input().split()) + +# 邻接矩阵 +grid = [] +for i in range(n): + grid.append(list(map(int, input().split()))) + +# 清除边界上的连通分量 +for i in range(n): + if grid[i][0] == 1: + dfs(grid, i, 0) + if grid[i][m - 1] == 1: + dfs(grid, i, m - 1) + +for j in range(m): + if grid[0][j] == 1: + dfs(grid, 0, j) + if grid[n - 1][j] == 1: + dfs(grid, n - 1, j) + +count = 0 # 将count重置为0 +# 统计内部所有剩余的连通分量 +for i in range(n): + for j in range(m): + if grid[i][j] == 1: + dfs(grid, i, j) + +print(count) +``` + +#### 广搜版 ```python 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) # 定义四个方向、孤岛面积(遍历完边缘后会被重置) @@ -293,17 +341,22 @@ def bfs(r, c): for i in range(n): - if g[i][0] == 1: bfs(i, 0) - if g[i][m-1] == 1: bfs(i, m-1) + if g[i][0] == 1: + bfs(i, 0) + if g[i][m-1] == 1: + bfs(i, m-1) for i in range(m): - if g[0][i] == 1: bfs(0, i) - if g[n-1][i] == 1: bfs(n-1, i) + if g[0][i] == 1: + bfs(0, i) + if g[n-1][i] == 1: + bfs(n-1, i) count = 0 for i in range(n): for j in range(m): - if g[i][j] == 1: bfs(i, j) + if g[i][j] == 1: + bfs(i, j) print(count) ``` From 4ddbb265e47e79919ad501c087919f99a4615612 Mon Sep 17 00:00:00 2001 From: swjtuhjf Date: Tue, 12 Nov 2024 10:38:41 +0800 Subject: [PATCH 49/81] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=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=20pyth?= =?UTF-8?q?on3=20SPFA=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kamacoder/0095.城市间货物运输II.md | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/problems/kamacoder/0095.城市间货物运输II.md b/problems/kamacoder/0095.城市间货物运输II.md index ac6ccf3c..a88e462a 100644 --- a/problems/kamacoder/0095.城市间货物运输II.md +++ b/problems/kamacoder/0095.城市间货物运输II.md @@ -333,6 +333,8 @@ public class Main { ### Python +Bellman-Ford方法求解含有负回路的最短路问题 + ```python import sys @@ -388,6 +390,52 @@ if __name__ == "__main__": ``` +SPFA方法求解含有负回路的最短路问题 + +```python +from collections import deque +from math import inf + +def main(): + n, m = [int(i) for i in input().split()] + graph = [[] for _ in range(n+1)] + min_dist = [inf for _ in range(n+1)] + count = [0 for _ in range(n+1)] # 记录节点加入队列的次数 + for _ in range(m): + s, t, v = [int(i) for i in input().split()] + graph[s].append([t, v]) + + min_dist[1] = 0 # 初始化 + count[1] = 1 + d = deque([1]) + flag = False + + while d: # 主循环 + cur_node = d.popleft() + for next_node, val in graph[cur_node]: + if min_dist[next_node] > min_dist[cur_node] + val: + min_dist[next_node] = min_dist[cur_node] + val + count[next_node] += 1 + if next_node not in d: + d.append(next_node) + if count[next_node] == n: # 如果某个点松弛了n次,说明有负回路 + flag = True + if flag: + break + + if flag: + print("circle") + else: + if min_dist[-1] == inf: + print("unconnected") + else: + print(min_dist[-1]) + + +if __name__ == "__main__": + main() +``` + ### Go ### Rust From 947424d311d767dec59f5820b9a83f51da5c2bcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=B6=E7=AC=9B?= <128707187+catherinexrk@users.noreply.github.com> Date: Tue, 12 Nov 2024 10:52:30 +0800 Subject: [PATCH 50/81] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=200103.=E6=B0=B4?= =?UTF-8?q?=E6=B5=81=E9=97=AE=E9=A2=98.=20Go=E8=AF=AD=E8=A8=80=20DFS?= =?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/kamacoder/0103.水流问题.md | 75 +++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/problems/kamacoder/0103.水流问题.md b/problems/kamacoder/0103.水流问题.md index 9a34bf09..65d36e48 100644 --- a/problems/kamacoder/0103.水流问题.md +++ b/problems/kamacoder/0103.水流问题.md @@ -413,6 +413,81 @@ if __name__ == "__main__": ``` ### Go +```go +package main + +import ( + "os" + "fmt" + "strings" + "strconv" + "bufio" +) + +var directions = [][]int{{0, -1}, {0, 1}, {-1, 0}, {1, 0}} // 四个方向的偏移量 + +func main() { + scanner := bufio.NewScanner(os.Stdin) + + scanner.Scan() + lineList := strings.Fields(scanner.Text()) + N, _ := strconv.Atoi(lineList[0]) + M, _ := strconv.Atoi(lineList[1]) + + grid := make([][]int, N) + visited := make([][]bool, N) // 用于标记是否访问过 + for i := 0; i < N; i++ { + grid[i] = make([]int, M) + visited[i] = make([]bool, M) + scanner.Scan() + lineList = strings.Fields(scanner.Text()) + + for j := 0; j < M; j++ { + grid[i][j], _ = strconv.Atoi(lineList[j]) + } + } + + // 遍历每个单元格,使用DFS检查是否可达两组边界 + for i := 0; i < N; i++ { + for j := 0; j < M; j++ { + canReachFirst, canReachSecond := dfs(grid, visited, i, j) + if canReachFirst && canReachSecond { + fmt.Println(strconv.Itoa(i) + " " + strconv.Itoa(j)) + } + } + } +} + +func dfs(grid [][]int, visited [][]bool, startx int, starty int) (bool, bool) { + visited[startx][starty] = true + canReachFirst := startx == 0 || starty == 0 || startx == len(grid)-1 || starty == len(grid[0])-1 + canReachSecond := startx == len(grid)-1 || starty == len(grid[0])-1 || startx == 0 || starty == 0 + + if canReachFirst && canReachSecond { + return true, true + } + + for _, direction := range directions { + nextx := startx + direction[0] + nexty := starty + direction[1] + + if nextx < 0 || nextx >= len(grid) || nexty < 0 || nexty >= len(grid[0]) { + continue + } + + if grid[nextx][nexty] <= grid[startx][starty] && !visited[nextx][nexty] { + hasReachFirst, hasReachSecond := dfs(grid, visited, nextx, nexty) + if !canReachFirst { + canReachFirst = hasReachFirst + } + if !canReachSecond { + canReachSecond = hasReachSecond + } + } + } + return canReachFirst, canReachSecond +} +``` ### Rust From 6c497c692b53da154458e82d719cc9c25268e132 Mon Sep 17 00:00:00 2001 From: swjtuhjf Date: Tue, 12 Nov 2024 14:04:38 +0800 Subject: [PATCH 51/81] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=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=20pyt?= =?UTF-8?q?hon3=20SPFA=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../0096.城市间货物运输III.md | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/problems/kamacoder/0096.城市间货物运输III.md b/problems/kamacoder/0096.城市间货物运输III.md index a41332cf..109027b1 100644 --- a/problems/kamacoder/0096.城市间货物运输III.md +++ b/problems/kamacoder/0096.城市间货物运输III.md @@ -703,6 +703,9 @@ public class Main { ``` ### Python + +Bellman-Ford方法求解单源有限最短路 + ```python def main(): # 輸入 @@ -736,6 +739,48 @@ def main(): +if __name__ == "__main__": + main() +``` + +SPFA方法求解单源有限最短路 + +```python +from collections import deque +from math import inf + + +def main(): + n, m = [int(i) for i in input().split()] + graph = [[] for _ in range(n+1)] + for _ in range(m): + v1, v2, val = [int(i) for i in input().split()] + graph[v1].append([v2, val]) + src, dst, k = [int(i) for i in input().split()] + min_dist = [inf for _ in range(n+1)] + min_dist[src] = 0 # 初始化起点的距离 + que = deque([src]) + + while k != -1 and que: + visited = [False for _ in range(n+1)] # 用于保证每次松弛时一个节点最多加入队列一次 + que_size = len(que) + temp_dist = min_dist.copy() # 用于记录上一次遍历的结果 + for _ in range(que_size): + cur_node = que.popleft() + for next_node, val in graph[cur_node]: + if min_dist[next_node] > temp_dist[cur_node] + val: + min_dist[next_node] = temp_dist[cur_node] + val + if not visited[next_node]: + que.append(next_node) + visited[next_node] = True + k -= 1 + + if min_dist[dst] == inf: + print("unreachable") + else: + print(min_dist[dst]) + + if __name__ == "__main__": main() ``` From 50472c381cd423ac12ff4c6eb8bb6126a4f5a2d1 Mon Sep 17 00:00:00 2001 From: markwang Date: Tue, 12 Nov 2024 14:31:02 +0800 Subject: [PATCH 52/81] =?UTF-8?q?143.=E9=87=8D=E6=8E=92=E9=93=BE=E8=A1=A8?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0Go=E6=96=B9=E6=B3=95=E4=B8=80=E5=92=8C?= =?UTF-8?q?=E6=96=B9=E6=B3=95=E4=BA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0143.重排链表.md | 83 +++++++++++++++++++++++++++++++++-- 1 file changed, 80 insertions(+), 3 deletions(-) diff --git a/problems/0143.重排链表.md b/problems/0143.重排链表.md index 87075431..ccddef5b 100644 --- a/problems/0143.重排链表.md +++ b/problems/0143.重排链表.md @@ -38,7 +38,7 @@ public: cur = head; int i = 1; int j = vec.size() - 1; // i j为之前前后的双指针 - int count = 0; // 计数,偶数去后面,奇数取前面 + int count = 0; // 计数,偶数取后面,奇数取前面 while (i <= j) { if (count % 2 == 0) { cur->next = vec[j]; @@ -73,7 +73,7 @@ public: } cur = head; - int count = 0; // 计数,偶数去后面,奇数取前面 + int count = 0; // 计数,偶数取后面,奇数取前面 ListNode* node; while(que.size()) { if (count % 2 == 0) { @@ -338,8 +338,85 @@ class Solution: return pre ``` ### Go + ```go -# 方法三 分割链表 +// 方法一 数组模拟 +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ +func reorderList(head *ListNode) { + vec := make([]*ListNode, 0) + cur := head + if cur == nil { + return + } + for cur != nil { + vec = append(vec, cur) + cur = cur.Next + } + cur = head + i := 1 + j := len(vec) - 1 // i j为前后的双指针 + count := 0 // 计数,偶数取后面,奇数取前面 + for i <= j { + if count % 2 == 0 { + cur.Next = vec[j] + j-- + } else { + cur.Next = vec[i] + i++ + } + cur = cur.Next + count++ + } + cur.Next = nil // 注意结尾 +} +``` + +```go +// 方法二 双向队列模拟 +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ +func reorderList(head *ListNode) { + que := make([]*ListNode, 0) + cur := head + if cur == nil { + return + } + + for cur.Next != nil { + que = append(que, cur.Next) + cur = cur.Next + } + + cur = head + count := 0 // 计数,偶数取后面,奇数取前面 + for len(que) > 0 { + if count % 2 == 0 { + cur.Next = que[len(que)-1] + que = que[:len(que)-1] + } else { + cur.Next = que[0] + que = que[1:] + } + count++ + cur = cur.Next + } + cur.Next = nil // 注意结尾 +} +``` + +```go +// 方法三 分割链表 func reorderList(head *ListNode) { var slow=head var fast=head From 0f152be27b34a82fa3882ffb5c86c55572550de1 Mon Sep 17 00:00:00 2001 From: lm10 Date: Tue, 12 Nov 2024 17:05:27 +0800 Subject: [PATCH 53/81] =?UTF-8?q?=E6=B7=BB=E5=8A=A0:0105.=E6=9C=89?= =?UTF-8?q?=E5=90=91=E5=9B=BE=E7=9A=84=E5=AE=8C=E5=85=A8=E5=8F=AF=E8=BE=BE?= =?UTF-8?q?=E6=80=A7Javascript=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../0105.有向图的完全可达性.md | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/problems/kamacoder/0105.有向图的完全可达性.md b/problems/kamacoder/0105.有向图的完全可达性.md index 838b0212..923fb6e4 100644 --- a/problems/kamacoder/0105.有向图的完全可达性.md +++ b/problems/kamacoder/0105.有向图的完全可达性.md @@ -491,6 +491,54 @@ func main() { ### Javascript +```javascript +const rl = require('readline').createInterface({ + input:process.stdin, + output:process.stdout +}) + +let inputLines = [] + +rl.on('line' , (line)=>{ + inputLines.push(line) +}) + +rl.on('close',()=>{ + let [n , edgesCount]= inputLines[0].trim().split(' ').map(Number) + + let graph = Array.from({length:n+1} , ()=>{return[]}) + + for(let i = 1 ; i < inputLines.length ; i++ ){ + let [from , to] = inputLines[i].trim().split(' ').map(Number) + graph[from].push(to) + } + + let visited = new Array(n + 1).fill(false) + + let dfs = (graph , key , visited)=>{ + if(visited[key]){ + return + } + + visited[key] = true + for(let nextKey of graph[key]){ + dfs(graph,nextKey , visited) + } + } + + dfs(graph , 1 , visited) + + for(let i = 1 ; i <= n;i++){ + if(visited[i] === false){ + console.log(-1) + return + } + } + console.log(1) + +}) +``` + ### TypeScript ### PhP From a0690ff730c6569aa0d39cb3b001e4068a6fc89a Mon Sep 17 00:00:00 2001 From: namewyf Date: Tue, 12 Nov 2024 23:03:01 +0800 Subject: [PATCH 54/81] =?UTF-8?q?=E5=BC=80=E5=8F=91=E5=95=86=E8=B4=AD?= =?UTF-8?q?=E4=B9=B0=E5=9C=9F=E5=9C=B0=E8=A7=A3=E6=B3=95=20JavaScript?= =?UTF-8?q?=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kamacoder/0044.开发商购买土地.md | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/problems/kamacoder/0044.开发商购买土地.md b/problems/kamacoder/0044.开发商购买土地.md index ea2c696e..739e2cad 100644 --- a/problems/kamacoder/0044.开发商购买土地.md +++ b/problems/kamacoder/0044.开发商购买土地.md @@ -388,6 +388,62 @@ if __name__ == "__main__": main() ``` + +### JavaScript + +前缀和 +```js +function func() { + const readline = require('readline') + const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout + }) + let inputLines = [] + rl.on('line', function (line) { + inputLines.push(line.trim()) + }) + + rl.on('close', function () { + let [n, m] = inputLines[0].split(" ").map(Number) + let c = new Array(n).fill(0) + let r = new Array(m).fill(0) + let arr = new Array(n) + let sum = 0//数组总和 + let min = Infinity//设置最小值的初始值为无限大 + //定义数组 + for (let s = 0; s < n; s++) { + arr[s] = inputLines[s + 1].split(" ").map(Number) + } + //每一行的和 + for (let i = 0; i < n; i++) { + for (let j = 0; j < m; j++) { + c[i] += arr[i][j] + sum += arr[i][j] + } + } + //每一列的和 + for (let i = 0; i < n; i++) { + for (let j = 0; j < m; j++) { + r[j] += arr[i][j] + } + } + let sum1 = 0, sum2 = 0 + //横向切割 + for (let i = 0; i < n; i++) { + sum1 += c[i] + min = min < Math.abs(sum - 2 * sum1) ? min : Math.abs(sum - 2 * sum1) + } + //纵向切割 + for (let j = 0; j < m; j++) { + sum2 += r[j] + min = min < Math.abs(sum - 2 * sum2) ? min : Math.abs(sum - 2 * sum2) + } + console.log(min); + }) +} +``` + ### C 前缀和 From 2d266b576653720ff16b0a3dfa635b72f5ffa57d Mon Sep 17 00:00:00 2001 From: liao junwu Date: Thu, 14 Nov 2024 23:24:17 +0800 Subject: [PATCH 55/81] [0739 temperature] add C version add C version for 0739: temperature Signed-off-by: liao junwu --- problems/0739.每日温度.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/problems/0739.每日温度.md b/problems/0739.每日温度.md index 45af5286..dd633aed 100644 --- a/problems/0739.每日温度.md +++ b/problems/0739.每日温度.md @@ -215,6 +215,38 @@ public: ## 其他语言版本 +### C: + +```C +/** + * Note: The returned array must be malloced, assume caller calls free(). + */ +int* dailyTemperatures(int* temperatures, int temperaturesSize, int* returnSize) { + int len = temperaturesSize; + *returnSize = len; + + int *result = (int *)malloc(sizeof(int) * len); + memset(result, 0x00, sizeof(int) * len); + + int stack[len]; + memset(stack, 0x00, sizeof(stack)); + int top = 0; + + for (int i = 1; i < len; i++) { + if (temperatures[i] <= temperatures[stack[top]]) { /* push */ + stack[++top] = i; + } else { + while (top >= 0 && temperatures[i] > temperatures[stack[top]]) { /* stack not empty */ + result[stack[top]] = i - stack[top]; + top--; /* pop */ + } + stack[++top] = i; /* push */ + } + } + return result; +} +``` + ### Java: ```java From da88f5e4c1407d99b46f087a6d5d10f6e685844e Mon Sep 17 00:00:00 2001 From: liao junwu Date: Sat, 16 Nov 2024 15:42:44 +0800 Subject: [PATCH 56/81] [0496 the next bigger element] add C version add C version for 0496: the next bigger element Signed-off-by: liao junwu --- problems/0496.下一个更大元素I.md | 56 +++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/problems/0496.下一个更大元素I.md b/problems/0496.下一个更大元素I.md index 54182d30..02e73a58 100644 --- a/problems/0496.下一个更大元素I.md +++ b/problems/0496.下一个更大元素I.md @@ -195,6 +195,62 @@ public: 建议大家把情况一二三想清楚了,先写出版本一的代码,然后在其基础上在做精简! ## 其他语言版本 + +### C + +``` C +/* 先用单调栈的方法计算出结果,再根据nums1中的元素去查找对应的结果 */ +/** + * Note: The returned array must be malloced, assume caller calls free(). + */ +int* nextGreaterElement(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize) { + + /* stcak */ + int top = -1; + int stack_len = nums2Size; + int stack[stack_len]; + //memset(stack, 0x00, sizeof(stack)); + + /* nums2 result */ + int* result_nums2 = (int *)malloc(sizeof(int) * nums2Size); + //memset(result_nums2, 0x00, sizeof(int) * nums2Size); + + /* result */ + int* result = (int *)malloc(sizeof(int) * nums1Size); + //memset(result, 0x00, sizeof(int) * nums1Size); + *returnSize = nums1Size; + + /* init */ + stack[++top] = 0; /* stack loaded with array subscripts */ + + for (int i = 0; i < nums2Size; i++) { + result_nums2[i] = -1; + } + + /* get the result_nums2 */ + for (int i = 1; i < nums2Size; i++) { + if (nums2[i] <= nums2[stack[top]]) { + stack[++top] = i; /* push */ + } else { + while ((top >= 0) && (nums2[i] > nums2[stack[top]])) { + result_nums2[stack[top]] = nums2[i]; + top--; /* pop */ + } + stack[++top] = i; + } + } + + /* get the result */ + for (int i = 0; i < nums1Size; i++) { + for (int j = 0; j < nums2Size; j++) { + if (nums1[i] == nums2[j]) { + result[i] = result_nums2[j]; + } + } + } + return result; +} +``` ### Java ```java From 6901cb345efc05009c029ee121592e3f66ec182a Mon Sep 17 00:00:00 2001 From: lllyt8 Date: Sun, 17 Nov 2024 23:30:11 -0800 Subject: [PATCH 57/81] =?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 58/81] =?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 59/81] =?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 60/81] =?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 61/81] =?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数组的顺序。 -然后在问问题,目的性就很强了,群里的小伙伴也可以快速知道提问者的疑惑了。 +然后再问问题,目的性就很强了,群里的小伙伴也可以快速知道提问者的疑惑了。 **注意这里不是说不让大家问问题哈, 而是说问问题之前要有自己的思考,问题要问到点子上!** From 7d1cb13e748e6e265438ec7b772835eee412cb42 Mon Sep 17 00:00:00 2001 From: Leehouc <152672308+Leehouc@users.noreply.github.com> Date: Sun, 24 Nov 2024 21:30:18 +0800 Subject: [PATCH 62/81] =?UTF-8?q?Update=200108.=E5=86=97=E4=BD=99=E8=BF=9E?= =?UTF-8?q?=E6=8E=A5.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/kamacoder/0108.冗余连接.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/problems/kamacoder/0108.冗余连接.md b/problems/kamacoder/0108.冗余连接.md index 18a86ad6..6c393b4f 100644 --- a/problems/kamacoder/0108.冗余连接.md +++ b/problems/kamacoder/0108.冗余连接.md @@ -44,7 +44,7 @@ ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20240527110320.png) -图中的 1 2,2 3,1 3 等三条边在删除后都能使原图变为一棵合法的树。但是 1 3 由于是标准输出里最后出现的那条边,所以输出结果为 1 3 +图中的 1 2,2 3,1 3 等三条边在删除后都能使原图变为一棵合法的树。但是 1 3 由于是标准输入里最后出现的那条边,所以输出结果为 1 3 数据范围: From 4d382794537f44bba8028b8e005df25fb29a43b6 Mon Sep 17 00:00:00 2001 From: ASGPIPO Date: Mon, 2 Dec 2024 16:48:06 +0800 Subject: [PATCH 63/81] =?UTF-8?q?fix:=20=E6=9B=B4=E6=96=B0README=E4=B8=AD?= =?UTF-8?q?=20=E5=AD=97=E7=AC=A6=E4=B8=B2=E4=B8=8E=E5=8F=8C=E6=8C=87?= =?UTF-8?q?=E9=92=88=E6=9D=BF=E5=9D=97=E9=A2=98=E7=9B=AE=E9=93=BE=E6=8E=A5?= =?UTF-8?q?=E9=94=99=E8=AF=AF=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3e3b6786..b326046e 100644 --- a/README.md +++ b/README.md @@ -141,9 +141,9 @@ 1. [字符串:344.反转字符串](./problems/0344.反转字符串.md) 2. [字符串:541.反转字符串II](./problems/0541.反转字符串II.md) -3. [字符串:替换数字](./problems/kama54.替换数字.md) +3. [字符串:替换数字](./problems/kamacoder/0054.替换数字.md) 4. [字符串:151.翻转字符串里的单词](./problems/0151.翻转字符串里的单词.md) -5. [字符串:右旋字符串](./problems/kama55.右旋字符串.md) +5. [字符串:右旋字符串](./problems/kamacoder/0055.右旋字符串.md) 6. [帮你把KMP算法学个通透](./problems/0028.实现strStr.md) 8. [字符串:459.重复的子字符串](./problems/0459.重复的子字符串.md) 9. [字符串:总结篇!](./problems/字符串总结.md) @@ -154,7 +154,7 @@ 1. [数组:27.移除元素](./problems/0027.移除元素.md) 2. [字符串:344.反转字符串](./problems/0344.反转字符串.md) -3. [字符串:替换数字](./problems/kama54.替换数字.md) +3. [字符串:替换数字](./problems/kamacoder/0054.替换数字.md) 4. [字符串:151.翻转字符串里的单词](./problems/0151.翻转字符串里的单词.md) 5. [链表:206.翻转链表](./problems/0206.翻转链表.md) 6. [链表:19.删除链表的倒数第 N 个结点](./problems/0019.删除链表的倒数第N个节点.md) From 5b94b448646e15507c07aa5c95337b2f1bd0f620 Mon Sep 17 00:00:00 2001 From: Yuan Yuan Date: Wed, 4 Dec 2024 12:29:18 -0600 Subject: [PATCH 64/81] =?UTF-8?q?feat:=20Updated=E9=A2=98=E7=9B=AE1365?= =?UTF-8?q?=EF=BC=8C=E6=8F=90=E4=BE=9B=E4=BA=86=E4=BD=BF=E7=94=A8=E6=95=B0?= =?UTF-8?q?=E7=BB=84=E8=BF=9B=E8=A1=8C=E5=93=88=E5=B8=8C=E7=9A=84=E8=A7=A3?= =?UTF-8?q?=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...65.有多少小于当前数字的数字.md | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/problems/1365.有多少小于当前数字的数字.md b/problems/1365.有多少小于当前数字的数字.md index 64f61096..22dd3226 100644 --- a/problems/1365.有多少小于当前数字的数字.md +++ b/problems/1365.有多少小于当前数字的数字.md @@ -138,7 +138,9 @@ public int[] smallerNumbersThanCurrent(int[] nums) { ### Python: -```python +> (版本一)使用字典 + +```python3 class Solution: def smallerNumbersThanCurrent(self, nums: List[int]) -> List[int]: res = nums[:] @@ -152,6 +154,23 @@ class Solution: return res ``` +> (版本二)使用数组 + +```python3 +class Solution: + def smallerNumbersThanCurrent(self, nums: List[int]) -> List[int]: + # 同步进行排序和创建新数组的操作,这样可以减少一次冗余的数组复制操作,以减少一次O(n) 的复制时间开销 + sort_nums = sorted(nums) + # 题意中 0 <= nums[i] <= 100,故range的参数设为101 + hash_lst = [0 for _ in range(101)] + # 从后向前遍历,这样hash里存放的就是相同元素最左面的数值和下标了 + for i in range(len(sort_nums)-1,-1,-1): + hash_lst[sort_nums[i]] = i + for i in range(len(nums)): + nums[i] = hash_lst[nums[i]] + return nums +``` + ### Go: ```go From 14223a2fa6c4a93d9e782a6b4e32e73682c5e051 Mon Sep 17 00:00:00 2001 From: Yuan Yuan Date: Wed, 4 Dec 2024 12:33:40 -0600 Subject: [PATCH 65/81] =?UTF-8?q?fix:=20Update=201365=EF=BC=8C=E5=BB=BA?= =?UTF-8?q?=E8=AE=AE=E4=B8=8D=E4=BD=BF=E7=94=A8built-in=20func=E4=BD=9C?= =?UTF-8?q?=E4=B8=BAvar=20name?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 题解中使用`hash`作为变量名,而hash本身也是python3的built-in函数,故建议更改变量名 --- problems/1365.有多少小于当前数字的数字.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/problems/1365.有多少小于当前数字的数字.md b/problems/1365.有多少小于当前数字的数字.md index 22dd3226..95a270ff 100644 --- a/problems/1365.有多少小于当前数字的数字.md +++ b/problems/1365.有多少小于当前数字的数字.md @@ -144,13 +144,13 @@ public int[] smallerNumbersThanCurrent(int[] nums) { class Solution: def smallerNumbersThanCurrent(self, nums: List[int]) -> List[int]: res = nums[:] - hash = dict() + hash_dict = dict() res.sort() # 从小到大排序之后,元素下标就是小于当前数字的数字 for i, num in enumerate(res): - if num not in hash.keys(): # 遇到了相同的数字,那么不需要更新该 number 的情况 - hash[num] = i + if num not in hash_dict.keys(): # 遇到了相同的数字,那么不需要更新该 number 的情况 + hash_dict[num] = i for i, num in enumerate(nums): - res[i] = hash[num] + res[i] = hash_dict[num] return res ``` From e1034946d5bc1f5a74341fa82c81413117bbbbc8 Mon Sep 17 00:00:00 2001 From: Yuan Yuan Date: Wed, 4 Dec 2024 12:35:06 -0600 Subject: [PATCH 66/81] =?UTF-8?q?typo:=20Update=201365=EF=BC=8CRust?= =?UTF-8?q?=E5=BB=BA=E8=AE=AE=E9=A6=96=E5=AD=97=E6=AF=8D=E5=A4=A7=E5=86=99?= =?UTF-8?q?=EF=BC=8C=E4=B8=8E=E5=85=B6=E4=BB=96=E8=AF=AD=E8=A8=80=E7=9B=B8?= =?UTF-8?q?=E5=90=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/1365.有多少小于当前数字的数字.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/problems/1365.有多少小于当前数字的数字.md b/problems/1365.有多少小于当前数字的数字.md index 95a270ff..d7de450b 100644 --- a/problems/1365.有多少小于当前数字的数字.md +++ b/problems/1365.有多少小于当前数字的数字.md @@ -279,7 +279,7 @@ function smallerNumbersThanCurrent(nums: number[]): number[] { }; ``` -### rust +### Rust ```rust use std::collections::HashMap; impl Solution { From 66caa02935bf372ac1df3e812e18aa7059fc1561 Mon Sep 17 00:00:00 2001 From: Yuan Yuan Date: Wed, 4 Dec 2024 12:43:06 -0600 Subject: [PATCH 67/81] =?UTF-8?q?feat:=20Update=201365=EF=BC=8C=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0python=E7=9A=84=E6=9A=B4=E5=8A=9B=E6=B3=95=EF=BC=8C?= =?UTF-8?q?=E5=B9=B6=E5=B0=86=E5=93=88=E5=B8=8C=E6=B3=95=E7=9A=84=E4=B8=A4?= =?UTF-8?q?=E7=A7=8D=E6=96=B9=E6=B3=95=E5=90=88=E5=B9=B6=E5=86=99=E5=9C=A8?= =?UTF-8?q?=E4=B8=80=E8=B5=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...65.有多少小于当前数字的数字.md | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/problems/1365.有多少小于当前数字的数字.md b/problems/1365.有多少小于当前数字的数字.md index d7de450b..b34ba3da 100644 --- a/problems/1365.有多少小于当前数字的数字.md +++ b/problems/1365.有多少小于当前数字的数字.md @@ -138,10 +138,28 @@ public int[] smallerNumbersThanCurrent(int[] nums) { ### Python: -> (版本一)使用字典 +> 暴力法 ```python3 class Solution: + def smallerNumbersThanCurrent(self, nums: List[int]) -> List[int]: + res = [0 for _ in range(len(nums))] + for i in range(len(nums)): + cnt = 0 + for j in range(len(nums)): + if j == i: + continue + if nums[i] > nums[j]: + cnt += 1 + res[i] = cnt + return res +``` + +> 排序+hash + +```python3 +class Solution: + # 方法一:使用字典 def smallerNumbersThanCurrent(self, nums: List[int]) -> List[int]: res = nums[:] hash_dict = dict() @@ -152,12 +170,8 @@ class Solution: for i, num in enumerate(nums): res[i] = hash_dict[num] return res -``` -> (版本二)使用数组 - -```python3 -class Solution: + # 方法二:使用数组 def smallerNumbersThanCurrent(self, nums: List[int]) -> List[int]: # 同步进行排序和创建新数组的操作,这样可以减少一次冗余的数组复制操作,以减少一次O(n) 的复制时间开销 sort_nums = sorted(nums) From 53397d452ecc3d5b4612eb605dc577609edccb7b Mon Sep 17 00:00:00 2001 From: Yuan Yuan Date: Wed, 4 Dec 2024 12:45:00 -0600 Subject: [PATCH 68/81] =?UTF-8?q?docs:=20Update=201365=EF=BC=8C=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E5=86=92=E5=8F=B7=EF=BC=8C=E7=BB=9F=E4=B8=80=E6=A0=BC?= =?UTF-8?q?=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/1365.有多少小于当前数字的数字.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/problems/1365.有多少小于当前数字的数字.md b/problems/1365.有多少小于当前数字的数字.md index b34ba3da..722fcb17 100644 --- a/problems/1365.有多少小于当前数字的数字.md +++ b/problems/1365.有多少小于当前数字的数字.md @@ -138,7 +138,7 @@ public int[] smallerNumbersThanCurrent(int[] nums) { ### Python: -> 暴力法 +> 暴力法: ```python3 class Solution: @@ -155,7 +155,7 @@ class Solution: return res ``` -> 排序+hash +> 排序+hash: ```python3 class Solution: @@ -274,7 +274,7 @@ function smallerNumbersThanCurrent(nums: number[]): number[] { }; ``` -> 排序+hash +> 排序+hash: ```typescript function smallerNumbersThanCurrent(nums: number[]): number[] { From 7ead61625d0f85890034bb43c0f4a255a8820b19 Mon Sep 17 00:00:00 2001 From: Yuan Yuan Date: Wed, 4 Dec 2024 12:47:57 -0600 Subject: [PATCH 69/81] =?UTF-8?q?docs:=20Update=201365=EF=BC=8C=E7=BB=9F?= =?UTF-8?q?=E4=B8=80=E4=B8=BA=E4=B8=AD=E6=96=87=E5=86=92=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/1365.有多少小于当前数字的数字.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/problems/1365.有多少小于当前数字的数字.md b/problems/1365.有多少小于当前数字的数字.md index 722fcb17..f0a77f55 100644 --- a/problems/1365.有多少小于当前数字的数字.md +++ b/problems/1365.有多少小于当前数字的数字.md @@ -115,7 +115,7 @@ public: ## 其他语言版本 -### Java: +### Java: ```Java public int[] smallerNumbersThanCurrent(int[] nums) { @@ -253,7 +253,7 @@ var smallerNumbersThanCurrent = function(nums) { }; ``` -### TypeScript: +### TypeScript: > 暴力法: @@ -293,7 +293,7 @@ function smallerNumbersThanCurrent(nums: number[]): number[] { }; ``` -### Rust +### Rust: ```rust use std::collections::HashMap; impl Solution { From 4a9cfb56048e10e688745605289cbe76de84a0bf Mon Sep 17 00:00:00 2001 From: Tony Date: Fri, 6 Dec 2024 17:43:53 +0800 Subject: [PATCH 70/81] =?UTF-8?q?=E7=8E=B0=E6=9C=89=E8=A7=A3=E6=B3=95pytho?= =?UTF-8?q?n=E8=B6=85=E6=97=B6=EF=BC=8C=E9=80=9A=E8=BF=87=E5=87=8F?= =?UTF-8?q?=E5=B0=91=E9=80=92=E5=BD=92=E6=AC=A1=E6=95=B0=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0037.解数独.md | 80 +++++++++++++++++++++++--------------- 1 file changed, 48 insertions(+), 32 deletions(-) diff --git a/problems/0037.解数独.md b/problems/0037.解数独.md index 6a9f69bd..5f3f881c 100644 --- a/problems/0037.解数独.md +++ b/problems/0037.解数独.md @@ -366,40 +366,56 @@ class Solution: """ Do not return anything, modify board in-place instead. """ - self.backtracking(board) + row_used = [set() for _ in range(9)] + col_used = [set() for _ in range(9)] + box_used = [set() for _ in range(9)] + for row in range(9): + for col in range(9): + num = board[row][col] + if num == ".": + continue + row_used[row].add(num) + col_used[col].add(num) + box_used[(row // 3) * 3 + col // 3].add(num) + self.backtracking(0, 0, board, row_used, col_used, box_used) - def backtracking(self, board: List[List[str]]) -> bool: - # 若有解,返回True;若无解,返回False - for i in range(len(board)): # 遍历行 - for j in range(len(board[0])): # 遍历列 - # 若空格内已有数字,跳过 - if board[i][j] != '.': continue - for k in range(1, 10): - if self.is_valid(i, j, k, board): - board[i][j] = str(k) - if self.backtracking(board): return True - board[i][j] = '.' - # 若数字1-9都不能成功填入空格,返回False无解 - return False - return True # 有解 + def backtracking( + self, + row: int, + col: int, + board: List[List[str]], + row_used: List[List[int]], + col_used: List[List[int]], + box_used: List[List[int]], + ) -> bool: + if row == 9: + return True - def is_valid(self, row: int, col: int, val: int, board: List[List[str]]) -> bool: - # 判断同一行是否冲突 - for i in range(9): - if board[row][i] == str(val): - return False - # 判断同一列是否冲突 - for j in range(9): - if board[j][col] == str(val): - return False - # 判断同一九宫格是否有冲突 - start_row = (row // 3) * 3 - start_col = (col // 3) * 3 - for i in range(start_row, start_row + 3): - for j in range(start_col, start_col + 3): - if board[i][j] == str(val): - return False - return True + next_row, next_col = (row, col + 1) if col < 8 else (row + 1, 0) + if board[row][col] != ".": + return self.backtracking( + next_row, next_col, board, row_used, col_used, box_used + ) + + for num in map(str, range(1, 10)): + if ( + num not in row_used[row] + and num not in col_used[col] + and num not in box_used[(row // 3) * 3 + col // 3] + ): + board[row][col] = num + row_used[row].add(num) + col_used[col].add(num) + box_used[(row // 3) * 3 + col // 3].add(num) + if self.backtracking( + next_row, next_col, board, row_used, col_used, box_used + ): + return True + board[row][col] = "." + row_used[row].remove(num) + col_used[col].remove(num) + box_used[(row // 3) * 3 + col // 3].remove(num) + return False ``` ### Go From 34d28a94245baaa9744d2a06d84c050f643aeb24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A8=8B=E5=BA=8F=E5=91=98Carl?= Date: Sun, 8 Dec 2024 16:17:59 +0800 Subject: [PATCH 71/81] =?UTF-8?q?Update=200015.=E4=B8=89=E6=95=B0=E4=B9=8B?= =?UTF-8?q?=E5=92=8C.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0015.三数之和.md | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/problems/0015.三数之和.md b/problems/0015.三数之和.md index 0d47bf48..349335d0 100644 --- a/problems/0015.三数之和.md +++ b/problems/0015.三数之和.md @@ -36,7 +36,7 @@ ### 哈希解法 -两层for循环就可以确定 a 和b 的数值了,可以使用哈希法来确定 0-(a+b) 是否在 数组里出现过,其实这个思路是正确的,但是我们有一个非常棘手的问题,就是题目中说的不可以包含重复的三元组。 +两层for循环就可以确定 两个数值,可以使用哈希法来确定 第三个数 0-(a+b) 或者 0 - (a + c) 是否在 数组里出现过,其实这个思路是正确的,但是我们有一个非常棘手的问题,就是题目中说的不可以包含重复的三元组。 把符合条件的三元组放进vector中,然后再去重,这样是非常费时的,很容易超时,也是这道题目通过率如此之低的根源所在。 @@ -51,10 +51,8 @@ class Solution { public: // 在一个数组中找到3个数形成的三元组,它们的和为0,不能重复使用(三数下标互不相同),且三元组不能重复。 - // 理论解法:a+b+c(存储)==0(检索) <=> c(存储)==0-(a+b)(检索) - // 实际解法:a+b+c(存储)==0(检索) <=> b(存储)==0-(a+c)(检索) + // b(存储)== 0-(a+c)(检索) vector> threeSum(vector& nums) { - // 本解法的内层循环一边存储一边检索,所以被存储的应该是b,而不是c vector> result; sort(nums.begin(), nums.end()); @@ -71,11 +69,7 @@ public: unordered_set set; for (int k = i + 1; k < nums.size(); k++) { - // [(-2x), ..., (x), (x), x, x, x, ...] - // eg. [0, 0, 0] - // eg. [-4, 2, 2] - // eg. [(-4), -1, 0, 0, 1, (2), (2), {2}, {2}, 3, 3] - // 去重b=c时的b和c,即第三个x到最后一个x需要被跳过 + // 去重b=c时的b和c if (k > i + 2 && nums[k] == nums[k - 1] && nums[k - 1] == nums[k - 2]) continue; @@ -83,7 +77,6 @@ public: int target = 0 - (nums[i] + nums[k]); if (set.find(target) != set.end()) { result.push_back({nums[i], target, nums[k]}); // nums[k]成为c - // 内层循环中,a固定,如果find到了和上轮一样的b,那么c也就和上轮一样,所以去重b set.erase(target); } else { From 451b02dd5d6986df59483ee9f2444acab5d6abe2 Mon Sep 17 00:00:00 2001 From: Alvinn <138186772+fubugun@users.noreply.github.com> Date: Mon, 9 Dec 2024 16:56:47 +0800 Subject: [PATCH 72/81] =?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 8572ec2d..8cd505a8 100644 --- a/problems/0236.二叉树的最近公共祖先.md +++ b/problems/0236.二叉树的最近公共祖先.md @@ -45,7 +45,7 @@ 那么二叉树如何可以自底向上查找呢? -回溯啊,二叉树回溯的过程就是从低到上。 +回溯啊,二叉树回溯的过程就是从底到上。 后序遍历(左右中)就是天然的回溯过程,可以根据左右子树的返回值,来处理中节点的逻辑。 From 0763f4b2fe5be95c9105c844e818759d44bfc745 Mon Sep 17 00:00:00 2001 From: Alvinn <138186772+fubugun@users.noreply.github.com> Date: Mon, 9 Dec 2024 16:58:02 +0800 Subject: [PATCH 73/81] =?UTF-8?q?Update=200019.=E5=88=A0=E9=99=A4=E9=93=BE?= =?UTF-8?q?=E8=A1=A8=E7=9A=84=E5=80=92=E6=95=B0=E7=AC=ACN=E4=B8=AA?= =?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/0019.删除链表的倒数第N个节点.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/problems/0019.删除链表的倒数第N个节点.md b/problems/0019.删除链表的倒数第N个节点.md index f0ef2366..fafef1f2 100644 --- a/problems/0019.删除链表的倒数第N个节点.md +++ b/problems/0019.删除链表的倒数第N个节点.md @@ -58,7 +58,7 @@ * fast和slow同时移动,直到fast指向末尾,如题: - +//图片中有错别词:应该将“只到”改为“直到” * 删除slow指向的下一个节点,如图: From d3dc9f51b7569329d2688eec3d0c23f457c18e02 Mon Sep 17 00:00:00 2001 From: Alvinn <138186772+fubugun@users.noreply.github.com> Date: Mon, 9 Dec 2024 17:01:20 +0800 Subject: [PATCH 74/81] =?UTF-8?q?Update=20=E8=B4=AA=E5=BF=83=E7=AE=97?= =?UTF-8?q?=E6=B3=95=E7=90=86=E8=AE=BA=E5=9F=BA=E7=A1=80.md?= 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 f042c0ac..6fde2dbb 100644 --- a/problems/贪心算法理论基础.md +++ b/problems/贪心算法理论基础.md @@ -78,7 +78,7 @@ * 求解每一个子问题的最优解 * 将局部最优解堆叠成全局最优解 -这个四步其实过于理论化了,我们平时在做贪心类的题目 很难去按照这四步去思考,真是有点“鸡肋”。 +这个四步其实过于理论化了,我们平时在做贪心类的题目时,如果按照这四步去思考,真是有点“鸡肋”。 做题的时候,只要想清楚 局部最优 是什么,如果推导出全局最优,其实就够了。 From a28c40a8bcbb068c9d2f9f4b902322ce04e888ef Mon Sep 17 00:00:00 2001 From: Alvinn <138186772+fubugun@users.noreply.github.com> Date: Mon, 9 Dec 2024 17:06:28 +0800 Subject: [PATCH 75/81] =?UTF-8?q?Update=2020201107=E5=9B=9E=E6=BA=AF?= =?UTF-8?q?=E5=91=A8=E6=9C=AB=E6=80=BB=E7=BB=93.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/周总结/20201107回溯周末总结.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/problems/周总结/20201107回溯周末总结.md b/problems/周总结/20201107回溯周末总结.md index 2d20a197..7e333c76 100644 --- a/problems/周总结/20201107回溯周末总结.md +++ b/problems/周总结/20201107回溯周末总结.md @@ -75,7 +75,7 @@ for (int i = startIndex; i < candidates.size() && sum + candidates[i] <= target; 除了这些难点,**本题还有细节,例如:切割过的地方不能重复切割所以递归函数需要传入i + 1**。 -所以本题应该是一个道hard题目了。 +所以本题应该是一道hard题目了。 **本题的树形结构中,和代码的逻辑有一个小出入,已经判断不是回文的子串就不会进入递归了,纠正如下:** From c6f44808a37f88bdb5164170042505ceb1d228a0 Mon Sep 17 00:00:00 2001 From: Alvinn <138186772+fubugun@users.noreply.github.com> Date: Mon, 9 Dec 2024 17:15:25 +0800 Subject: [PATCH 76/81] =?UTF-8?q?Update=200332.=E9=87=8D=E6=96=B0=E5=AE=89?= =?UTF-8?q?=E6=8E=92=E8=A1=8C=E7=A8=8B.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0332.重新安排行程.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/problems/0332.重新安排行程.md b/problems/0332.重新安排行程.md index ed8149d0..78e14074 100644 --- a/problems/0332.重新安排行程.md +++ b/problems/0332.重新安排行程.md @@ -172,7 +172,7 @@ if (result.size() == ticketNum + 1) { 回溯的过程中,如何遍历一个机场所对应的所有机场呢? -这里刚刚说过,在选择映射函数的时候,不能选择`unordered_map> targets`, 因为一旦有元素增删multiset的迭代器就会失效,当然可能有牛逼的容器删除元素迭代器不会失效,这里就不在讨论了。 +这里刚刚说过,在选择映射函数的时候,不能选择`unordered_map> targets`, 因为一旦有元素增删multiset的迭代器就会失效,当然可能有牛逼的容器删除元素迭代器不会失效,这里就不再讨论了。 **可以说本题既要找到一个对数据进行排序的容器,而且还要容易增删元素,迭代器还不能失效**。 From b4ebda4fc94e4505ff268ec0e08bd951911e26c5 Mon Sep 17 00:00:00 2001 From: C_W Date: Tue, 10 Dec 2024 16:52:12 +1100 Subject: [PATCH 77/81] =?UTF-8?q?=E6=B7=BB=E5=8A=A00028=E5=AE=9E=E7=8E=B0s?= =?UTF-8?q?trStr=20C=20=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0028.实现strStr.md | 64 +++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/problems/0028.实现strStr.md b/problems/0028.实现strStr.md index e0cb123e..63a08d96 100644 --- a/problems/0028.实现strStr.md +++ b/problems/0028.实现strStr.md @@ -1456,6 +1456,70 @@ public int[] GetNext(string needle) } ``` +### C: + +> 前缀表统一右移和减一 + +```c + +int *build_next(char* needle, int len) { + + int *next = (int *)malloc(len * sizeof(int)); + assert(next); // 确保分配成功 + + // 初始化next数组 + next[0] = -1; // next[0] 设置为 -1,表示没有有效前缀匹配 + if (len <= 1) { // 如果模式串长度小于等于 1,直接返回 + return next; + } + next[1] = 0; // next[1] 设置为 0,表示第一个字符没有公共前后缀 + + // 构建next数组, i 从模式串的第三个字符开始, j 指向当前匹配的最长前缀长度 + int i = 2, j = 0; + while (i < len) { + if (needle[i - 1] == needle[j]) { + j++; + next[i] = j; + i++; + } else if (j > 0) { + // 如果不匹配且 j > 0, 回退到次长匹配前缀的长度 + j = next[j]; + } else { + next[i] = 0; + i++; + } + } + return next; +} + +int strStr(char* haystack, char* needle) { + + int needle_len = strlen(needle); + int haystack_len = strlen(haystack); + + int *next = build_next(needle, needle_len); + + int i = 0, j = 0; // i 指向主串的当前起始位置, j 指向模式串的当前匹配位置 + while (i <= haystack_len - needle_len) { + if (haystack[i + j] == needle[j]) { + j++; + if (j == needle_len) { + free(next); + next = NULL + return i; + } + } else { + i += j - next[j]; // 调整主串的起始位置 + j = j > 0 ? next[j] : 0; + } + } + + free(next); + next = NULL; + return -1; +} +``` +

From 96bb3d1bfeb507859ad3fcc00bd809f913dbce7c Mon Sep 17 00:00:00 2001 From: holic-x <1301996554@qq.com> Date: Thu, 12 Dec 2024 10:33:08 +0800 Subject: [PATCH 78/81] =?UTF-8?q?docs=EF=BC=9A=E8=A1=A5=E5=85=85=E3=80=900?= =?UTF-8?q?096-=E5=9F=8E=E5=B8=82=E9=97=B4=E8=B4=A7=E7=89=A9=E8=BF=90?= =?UTF-8?q?=E8=BE=93III=E3=80=91JAVA=E7=89=88=E6=9C=AC=E7=9A=84SPFA?= =?UTF-8?q?=E6=80=9D=E8=B7=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 补充【0096-城市间货物运输III】JAVA版本的SPFA思路 --- .../0096.城市间货物运输III.md | 119 ++++++++++++++++++ 1 file changed, 119 insertions(+) diff --git a/problems/kamacoder/0096.城市间货物运输III.md b/problems/kamacoder/0096.城市间货物运输III.md index a3e9e840..08fd010c 100644 --- a/problems/kamacoder/0096.城市间货物运输III.md +++ b/problems/kamacoder/0096.城市间货物运输III.md @@ -702,6 +702,125 @@ public class Main { ``` +```java +class Edge { + public int u; // 边的端点1 + public int v; // 边的端点2 + public int val; // 边的权值 + + public Edge() { + } + + public Edge(int u, int v) { + this.u = u; + this.v = v; + this.val = 0; + } + + public Edge(int u, int v, int val) { + this.u = u; + this.v = v; + this.val = val; + } +} + +/** + * SPFA算法(版本3):处理含【负权回路】的有向图的最短路径问题 + * bellman_ford(版本3) 的队列优化算法版本 + * 限定起点、终点、至多途径k个节点 + */ +public class SPFAForSSSP { + + /** + * SPFA算法 + * + * @param n 节点个数[1,n] + * @param graph 邻接表 + * @param startIdx 开始节点(源点) + */ + public static int[] spfa(int n, List> graph, int startIdx, int k) { + // 定义最大范围 + int maxVal = Integer.MAX_VALUE; + // minDist[i] 源点到节点i的最短距离 + int[] minDist = new int[n + 1]; // 有效节点编号范围:[1,n] + Arrays.fill(minDist, maxVal); // 初始化为maxVal + minDist[startIdx] = 0; // 设置源点到源点的最短路径为0 + + // 定义queue记录每一次松弛更新的节点 + Queue queue = new LinkedList<>(); + queue.offer(startIdx); // 初始化:源点开始(queue和minDist的更新是同步的) + + + // SPFA算法核心:只对上一次松弛的时候更新过的节点关联的边进行松弛操作 + while (k + 1 > 0 && !queue.isEmpty()) { // 限定松弛 k+1 次 + int curSize = queue.size(); // 记录当前队列节点个数(上一次松弛更新的节点个数,用作分层统计) + while (curSize-- > 0) { //分层控制,限定本次松弛只针对上一次松弛更新的节点,不对新增的节点做处理 + // 记录当前minDist状态,作为本次松弛的基础 + int[] minDist_copy = Arrays.copyOfRange(minDist, 0, minDist.length); + + // 取出节点 + int cur = queue.poll(); + // 获取cur节点关联的边,进行松弛操作 + List relateEdges = graph.get(cur); + for (Edge edge : relateEdges) { + int u = edge.u; // 与`cur`对照 + int v = edge.v; + int weight = edge.val; + if (minDist_copy[u] + weight < minDist[v]) { + minDist[v] = minDist_copy[u] + weight; // 更新 + // 队列同步更新(此处有一个针对队列的优化:就是如果已经存在于队列的元素不需要重复添加) + if (!queue.contains(v)) { + queue.offer(v); // 与minDist[i]同步更新,将本次更新的节点加入队列,用做下一个松弛的参考基础 + } + } + } + } + // 当次松弛结束,次数-1 + k--; + } + + // 返回minDist + return minDist; + } + + public static void main(String[] args) { + // 输入控制 + Scanner sc = new Scanner(System.in); + System.out.println("1.输入N个节点、M条边(u v weight)"); + int n = sc.nextInt(); + int m = sc.nextInt(); + + System.out.println("2.输入M条边"); + List> graph = new ArrayList<>(); // 构建邻接表 + for (int i = 0; i <= n; i++) { + graph.add(new ArrayList<>()); + } + while (m-- > 0) { + int u = sc.nextInt(); + int v = sc.nextInt(); + int weight = sc.nextInt(); + graph.get(u).add(new Edge(u, v, weight)); + } + + System.out.println("3.输入src dst k(起点、终点、至多途径k个点)"); + int src = sc.nextInt(); + int dst = sc.nextInt(); + int k = sc.nextInt(); + + // 调用算法 + int[] minDist = SPFAForSSSP.spfa(n, graph, src, k); + // 校验起点->终点 + if (minDist[dst] == Integer.MAX_VALUE) { + System.out.println("unreachable"); + } else { + System.out.println("最短路径:" + minDist[n]); + } + } +} +``` + + + ### Python ```python def main(): From b5cbc15bcfe13b3e8a6e45cf0f4e584eddd434d9 Mon Sep 17 00:00:00 2001 From: holic-x <1301996554@qq.com> Date: Thu, 12 Dec 2024 16:53:50 +0800 Subject: [PATCH 79/81] =?UTF-8?q?docs=EF=BC=9A=E3=80=900097-=E5=B0=8F?= =?UTF-8?q?=E6=98=8E=E9=80=9B=E5=85=AC=E5=9B=AD=E3=80=91=E8=A1=A5=E5=85=85?= =?UTF-8?q?=20JAVA=E7=89=88=E6=9C=AC=E3=80=90=E5=9F=BA=E4=BA=8E=E4=B8=89?= =?UTF-8?q?=E7=BB=B4=E6=95=B0=E7=BB=84=E7=9A=84Floyd=E7=AE=97=E6=B3=95?= =?UTF-8?q?=E3=80=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit docs:【0097-小明逛公园】补充 JAVA版本【基于三维数组的Floyd算法】 --- problems/kamacoder/0097.小明逛公园.md | 65 ++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/problems/kamacoder/0097.小明逛公园.md b/problems/kamacoder/0097.小明逛公园.md index 8b3078fc..27ad0eb9 100644 --- a/problems/kamacoder/0097.小明逛公园.md +++ b/problems/kamacoder/0097.小明逛公园.md @@ -424,6 +424,71 @@ floyd算法的时间复杂度相对较高,适合 稠密图且源点较多的 ### Java +- 基于三维数组的Floyd算法 + +```java +public class FloydBase { + + // public static int MAX_VAL = Integer.MAX_VALUE; + public static int MAX_VAL = 10005; // 边的最大距离是10^4(不选用Integer.MAX_VALUE是为了避免相加导致数值溢出) + + public static void main(String[] args) { + // 输入控制 + Scanner sc = new Scanner(System.in); + System.out.println("1.输入N M"); + int n = sc.nextInt(); + int m = sc.nextInt(); + + System.out.println("2.输入M条边"); + + // ① dp定义(grid[i][j][k] 节点i到节点j 可能经过节点K(k∈[1,n]))的最短路径 + int[][][] grid = new int[n + 1][n + 1][n + 1]; + for (int i = 1; i <= n; i++) { + for (int j = 1; j <= n; j++) { + for (int k = 0; k <= n; k++) { + grid[i][j][k] = grid[j][i][k] = MAX_VAL; // 其余设置为最大值 + } + } + } + + // ② dp 推导:grid[i][j][k] = min{grid[i][k][k-1] + grid[k][j][k-1], grid[i][j][k-1]} + while (m-- > 0) { + int u = sc.nextInt(); + int v = sc.nextInt(); + int weight = sc.nextInt(); + grid[u][v][0] = grid[v][u][0] = weight; // 初始化(处理k=0的情况) ③ dp初始化 + } + + // ④ dp推导:floyd 推导 + for (int k = 1; k <= n; k++) { + for (int i = 1; i <= n; i++) { + for (int j = 1; j <= n; j++) { + grid[i][j][k] = Math.min(grid[i][k][k - 1] + grid[k][j][k - 1], grid[i][j][k - 1]); + } + } + } + + System.out.println("3.输入[起点-终点]计划个数"); + int x = sc.nextInt(); + + System.out.println("4.输入每个起点src 终点dst"); + + while (x-- > 0) { + int src = sc.nextInt(); + int dst = sc.nextInt(); + // 根据floyd推导结果输出计划路径的最小距离 + if (grid[src][dst][n] == MAX_VAL) { + System.out.println("-1"); + } else { + System.out.println(grid[src][dst][n]); + } + } + } +} +``` + + + ### Python 基于三维数组的Floyd From 0fa443ce1a234704898630c188640f4512e9f7d1 Mon Sep 17 00:00:00 2001 From: Yuan Yuan Date: Thu, 26 Dec 2024 14:03:38 -0600 Subject: [PATCH 80/81] =?UTF-8?q?fix:=20150=E9=A2=98=E6=9B=B4=E6=AD=A3Pyth?= =?UTF-8?q?on=E8=A7=A3=E6=B3=95=E4=B8=AD=E4=BD=BF=E7=94=A8eval()=E7=9A=84?= =?UTF-8?q?=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 此处原本提供的两个python解法是一样的,并无区别;更正为实际上真正使用eval()的方法。 --- problems/0150.逆波兰表达式求值.md | 32 +++++++---------------- 1 file changed, 9 insertions(+), 23 deletions(-) diff --git a/problems/0150.逆波兰表达式求值.md b/problems/0150.逆波兰表达式求值.md index 7d4031d7..4ffe950b 100644 --- a/problems/0150.逆波兰表达式求值.md +++ b/problems/0150.逆波兰表达式求值.md @@ -188,34 +188,20 @@ class Solution(object): return stack.pop() ``` -另一种可行,但因为使用eval相对较慢的方法: +另一种可行,但因为使用eval()相对较慢的方法: ```python -from operator import add, sub, mul - -def div(x, y): - # 使用整数除法的向零取整方式 - return int(x / y) if x * y > 0 else -(abs(x) // abs(y)) - class Solution(object): - op_map = {'+': add, '-': sub, '*': mul, '/': div} - - def evalRPN(self, tokens): - """ - :type tokens: List[str] - :rtype: int - """ + def evalRPN(self, tokens: List[str]) -> int: stack = [] for token in tokens: - if token in self.op_map: - op1 = stack.pop() - op2 = stack.pop() - operation = self.op_map[token] - stack.append(operation(op2, op1)) + # 判断是否为数字,因为isdigit()不识别负数,故需要排除第一位的符号 + if token.isdigit() or (len(token)>1 and token[1].isdigit()): + stack.append(token) else: - stack.append(int(token)) - return stack.pop() - - + op2 = stack.pop() + op1 = stack.pop() + stack.append(str(int(eval(op1 + token + op2)))) + return int(stack.pop()) ``` ### Go: From 0638ba5ad88909b1463ccb43f55cb06f9bc88d09 Mon Sep 17 00:00:00 2001 From: Yuan Yuan Date: Thu, 26 Dec 2024 14:09:06 -0600 Subject: [PATCH 81/81] =?UTF-8?q?docs:=20150=E9=A2=98=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0150.逆波兰表达式求值.md | 1 + 1 file changed, 1 insertion(+) diff --git a/problems/0150.逆波兰表达式求值.md b/problems/0150.逆波兰表达式求值.md index 4ffe950b..5fb28c29 100644 --- a/problems/0150.逆波兰表达式求值.md +++ b/problems/0150.逆波兰表达式求值.md @@ -200,6 +200,7 @@ class Solution(object): else: op2 = stack.pop() op1 = stack.pop() + # 由题意"The division always truncates toward zero",所以使用int()可以天然取整 stack.append(str(int(eval(op1 + token + op2)))) return int(stack.pop()) ```