From 2722fe7b5eceec7d746f94a63683430205839469 Mon Sep 17 00:00:00 2001 From: Steve2020 <841532108@qq.com> Date: Sun, 8 May 2022 11:07:39 +0800 Subject: [PATCH 01/17] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=EF=BC=880279.=E5=AE=8C?= =?UTF-8?q?=E5=85=A8=E5=B9=B3=E6=96=B9=E6=95=B0.md=EF=BC=89=EF=BC=9A?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0typescript=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0279.完全平方数.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/problems/0279.完全平方数.md b/problems/0279.完全平方数.md index 9bad2085..5b15639c 100644 --- a/problems/0279.完全平方数.md +++ b/problems/0279.完全平方数.md @@ -355,5 +355,24 @@ var numSquares2 = function(n) { }; ``` +TypeScript: + +```typescript +function numSquares(n: number): number { + const goodsNum: number = Math.floor(Math.sqrt(n)); + const dp: number[] = new Array(n + 1).fill(Infinity); + dp[0] = 0; + for (let i = 1; i <= goodsNum; i++) { + const tempVal: number = i * i; + for (let j = tempVal; j <= n; j++) { + dp[j] = Math.min(dp[j], dp[j - tempVal] + 1); + } + } + return dp[n]; +}; +``` + + + -----------------------
From 9b6a447674f3290541e46088962e1e3aa764d827 Mon Sep 17 00:00:00 2001 From: Hayden-Chang <62008508+Hayden-Chang@users.noreply.github.com> Date: Sun, 8 May 2022 14:20:09 +0800 Subject: [PATCH 02/17] explain the reason for reverse traversal --- problems/背包理论基础01背包-2.md | 1 + 1 file changed, 1 insertion(+) diff --git a/problems/背包理论基础01背包-2.md b/problems/背包理论基础01背包-2.md index dabdfb2d..ea7c53ad 100644 --- a/problems/背包理论基础01背包-2.md +++ b/problems/背包理论基础01背包-2.md @@ -136,6 +136,7 @@ dp[1] = dp[1 - weight[0]] + value[0] = 15 不可以! 因为一维dp的写法,背包容量一定是要倒序遍历(原因上面已经讲了),如果遍历背包容量放在上一层,那么每个dp[j]就只会放入一个物品,即:背包里只放入了一个物品。 +倒叙遍历的原因是,本质上还是一个对二维数组的遍历,并且右下角的值依赖上一层左上角的值,因此需要保证左边的值仍然是上一层的,从右向左覆盖。 (这里如果读不懂,就在回想一下dp[j]的定义,或者就把两个for循环顺序颠倒一下试试!) From 80167289e4895c4116b61a5c2a4fa22e9e2e88b5 Mon Sep 17 00:00:00 2001 From: Hayden-Chang <62008508+Hayden-Chang@users.noreply.github.com> Date: Sun, 8 May 2022 14:24:09 +0800 Subject: [PATCH 03/17] =?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-2.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/背包理论基础01背包-2.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/problems/背包理论基础01背包-2.md b/problems/背包理论基础01背包-2.md index ea7c53ad..eae01158 100644 --- a/problems/背包理论基础01背包-2.md +++ b/problems/背包理论基础01背包-2.md @@ -136,7 +136,8 @@ dp[1] = dp[1 - weight[0]] + value[0] = 15 不可以! 因为一维dp的写法,背包容量一定是要倒序遍历(原因上面已经讲了),如果遍历背包容量放在上一层,那么每个dp[j]就只会放入一个物品,即:背包里只放入了一个物品。 -倒叙遍历的原因是,本质上还是一个对二维数组的遍历,并且右下角的值依赖上一层左上角的值,因此需要保证左边的值仍然是上一层的,从右向左覆盖。 + +倒序遍历的原因是,本质上还是一个对二维数组的遍历,并且右下角的值依赖上一层左上角的值,因此需要保证左边的值仍然是上一层的,从右向左覆盖。 (这里如果读不懂,就在回想一下dp[j]的定义,或者就把两个for循环顺序颠倒一下试试!) From 2fb34b30b38ee73624d65d183955cef3a80caced Mon Sep 17 00:00:00 2001 From: Steve2020 <841532108@qq.com> Date: Sun, 8 May 2022 18:28:32 +0800 Subject: [PATCH 04/17] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=EF=BC=880139.=E5=8D=95?= =?UTF-8?q?=E8=AF=8D=E6=8B=86=E5=88=86.md=EF=BC=89:=E5=A2=9E=E5=8A=A0types?= =?UTF-8?q?cript=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0139.单词拆分.md | 42 +++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/problems/0139.单词拆分.md b/problems/0139.单词拆分.md index ac834f04..5b4e92b9 100644 --- a/problems/0139.单词拆分.md +++ b/problems/0139.单词拆分.md @@ -345,6 +345,48 @@ const wordBreak = (s, wordDict) => { } ``` +TypeScript: + +> 动态规划 + +```typescript +function wordBreak(s: string, wordDict: string[]): boolean { + const dp: boolean[] = new Array(s.length + 1).fill(false); + dp[0] = true; + for (let i = 1; i <= s.length; i++) { + for (let j = 0; j < i; j++) { + const tempStr: string = s.slice(j, i); + if (wordDict.includes(tempStr) && dp[j] === true) { + dp[i] = true; + break; + } + } + } + return dp[s.length]; +}; +``` + +> 记忆化回溯 + +```typescript +function wordBreak(s: string, wordDict: string[]): boolean { + // 只需要记忆结果为false的情况 + const memory: boolean[] = []; + return backTracking(s, wordDict, 0, memory); + function backTracking(s: string, wordDict: string[], startIndex: number, memory: boolean[]): boolean { + if (startIndex >= s.length) return true; + if (memory[startIndex] === false) return false; + for (let i = startIndex + 1, length = s.length; i <= length; i++) { + const str: string = s.slice(startIndex, i); + if (wordDict.includes(str) && backTracking(s, wordDict, i, memory)) + return true; + } + memory[startIndex] = false; + return false; + } +}; +``` + ----------------------- From 21475ad21864ce33fb5a6a113581f2c346be78b6 Mon Sep 17 00:00:00 2001 From: languagege Date: Mon, 9 May 2022 18:51:39 +0800 Subject: [PATCH 05/17] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E4=BA=86=E5=85=B6?= =?UTF-8?q?=E4=B8=AD=E4=B8=80=E4=B8=AA=E9=94=99=E5=88=AB=E5=AD=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0027.移除元素.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/problems/0027.移除元素.md b/problems/0027.移除元素.md index 590cf0b9..3a93ac88 100644 --- a/problems/0027.移除元素.md +++ b/problems/0027.移除元素.md @@ -81,7 +81,7 @@ public: **双指针法(快慢指针法)在数组和链表的操作中是非常常见的,很多考察数组、链表、字符串等操作的面试题,都使用双指针法。** -后序都会一一介绍到,本题代码如下: +后续都会一一介绍到,本题代码如下: ```CPP // 时间复杂度:O(n) From 75198263f91484020c4a4dde421d9ecd989422dd Mon Sep 17 00:00:00 2001 From: changjunkui <506678275@qq.com> Date: Tue, 10 May 2022 08:16:53 +0800 Subject: [PATCH 06/17] =?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 813e9b02..b3030a81 100644 --- a/problems/0019.删除链表的倒数第N个节点.md +++ b/problems/0019.删除链表的倒数第N个节点.md @@ -39,7 +39,7 @@ 分为如下几步: -* 首先这里我推荐大家使用虚拟头结点,这样方面处理删除实际头结点的逻辑,如果虚拟头结点不清楚,可以看这篇: [链表:听说用虚拟头节点会方便很多?](https://programmercarl.com/0203.移除链表元素.html) +* 首先这里我推荐大家使用虚拟头结点,这样方便处理删除实际头结点的逻辑,如果虚拟头结点不清楚,可以看这篇: [链表:听说用虚拟头节点会方便很多?](https://programmercarl.com/0203.移除链表元素.html) * 定义fast指针和slow指针,初始值为虚拟头结点,如图: From c62d518e149295783d219ec1871da84af8e5546e Mon Sep 17 00:00:00 2001 From: FizzerYu <36132150+FizzerYu@users.noreply.github.com> Date: Wed, 11 May 2022 01:17:08 +0800 Subject: [PATCH 07/17] fix bug --- problems/0701.二叉搜索树中的插入操作.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/problems/0701.二叉搜索树中的插入操作.md b/problems/0701.二叉搜索树中的插入操作.md index df6a3954..50e39ade 100644 --- a/problems/0701.二叉搜索树中的插入操作.md +++ b/problems/0701.二叉搜索树中的插入操作.md @@ -279,7 +279,7 @@ class Solution: root.right = self.insertIntoBST(root.right, val) # 返回更新后的以当前root为根节点的新树 - return roo + return root ``` **递归法** - 无返回值 From d92aa2c52f0589cca9dbf1a7624f9312395b63fe Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 11 May 2022 00:39:59 +0100 Subject: [PATCH 08/17] =?UTF-8?q?Add=200112.=E8=B7=AF=E5=BE=84=E6=80=BB?= =?UTF-8?q?=E5=92=8C.md=20C=E8=AF=AD=E8=A8=80=E8=A7=A3=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0112.路径总和.md | 57 +++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/problems/0112.路径总和.md b/problems/0112.路径总和.md index 41463ec1..6433996c 100644 --- a/problems/0112.路径总和.md +++ b/problems/0112.路径总和.md @@ -1006,6 +1006,63 @@ func traversal(_ cur: TreeNode?, count: Int) { } ``` +## C +0112.路径总和 +递归法: +```c +bool hasPathSum(struct TreeNode* root, int targetSum){ + // 递归结束条件:若当前节点不存在,返回false + if(!root) + return false; + // 若当前节点为叶子节点,且targetSum-root的值为0。(当前路径上的节点值的和满足条件)返回true + if(!root->right && !root->left && targetSum == root->val) + return true; + + // 查看左子树和右子树的所有节点是否满足条件 + return hasPathSum(root->right, targetSum - root->val) || hasPathSum(root->left, targetSum - root->val); +} +``` + +迭代法: +```c +// 存储一个节点以及当前的和 +struct Pair { + struct TreeNode* node; + int sum; +}; + +bool hasPathSum(struct TreeNode* root, int targetSum){ + struct Pair stack[1000]; + int stackTop = 0; + + // 若root存在,则将节点和值封装成一个pair入栈 + if(root) { + struct Pair newPair = {root, root->val}; + stack[stackTop++] = newPair; + } + + // 当栈不为空时 + while(stackTop) { + // 出栈栈顶元素 + struct Pair topPair = stack[--stackTop]; + // 若栈顶元素为叶子节点,且和为targetSum时,返回true + if(!topPair.node->left && !topPair.node->right && topPair.sum == targetSum) + return true; + + // 若当前栈顶节点有左右孩子,计算和并入栈 + if(topPair.node->left) { + struct Pair newPair = {topPair.node->left, topPair.sum + topPair.node->left->val}; + stack[stackTop++] = newPair; + } + if(topPair.node->right) { + struct Pair newPair = {topPair.node->right, topPair.sum + topPair.node->right->val}; + stack[stackTop++] = newPair; + } + } + return false; +} +``` + ----------------------- From cc2c2adb0987a5e2e82eed75a93be068da6388a4 Mon Sep 17 00:00:00 2001 From: ZongqinWang <1722249371@qq.com> Date: Wed, 11 May 2022 16:03:22 +0800 Subject: [PATCH 09/17] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=200977.=E6=9C=89?= =?UTF-8?q?=E5=BA=8F=E6=95=B0=E7=BB=84=E7=9A=84=E5=B9=B3=E6=96=B9.md=20Sca?= =?UTF-8?q?la=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0977.有序数组的平方.md | 34 ++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/problems/0977.有序数组的平方.md b/problems/0977.有序数组的平方.md index 24276bcf..0e79a3d6 100644 --- a/problems/0977.有序数组的平方.md +++ b/problems/0977.有序数组的平方.md @@ -358,7 +358,41 @@ class Solution { } } ``` +Scala: +双指针: +```scala +object Solution { + def sortedSquares(nums: Array[Int]): Array[Int] = { + val res: Array[Int] = new Array[Int](nums.length) + var top = nums.length - 1 + var i = 0 + var j = nums.length - 1 + while (i <= j) { + if (nums(i) * nums(i) <= nums(j) * nums(j)) { + // 当左侧平方小于等于右侧,res数组顶部放右侧的平方,并且top下移,j左移 + res(top) = nums(j) * nums(j) + top -= 1 + j -= 1 + } else { + // 当左侧平方大于右侧,res数组顶部放左侧的平方,并且top下移,i右移 + res(top) = nums(i) * nums(i) + top -= 1 + i += 1 + } + } + res + } +} +``` +骚操作(暴力思路): +```scala +object Solution { + def sortedSquares(nums: Array[Int]): Array[Int] = { + nums.map(x=>{x*x}).sortWith(_ < _) + } +} +``` ----------------------- From 842c04208b163c4782fb7070d949f5feb0c01bee Mon Sep 17 00:00:00 2001 From: Steve2020 <841532108@qq.com> Date: Wed, 11 May 2022 16:35:58 +0800 Subject: [PATCH 10/17] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=EF=BC=88=E8=83=8C?= =?UTF-8?q?=E5=8C=85=E9=97=AE=E9=A2=98=E7=90=86=E8=AE=BA=E5=9F=BA=E7=A1=80?= =?UTF-8?q?=E5=A4=9A=E9=87=8D=E8=83=8C=E5=8C=85.md=EF=BC=89=EF=BC=9A?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0typescript=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../背包问题理论基础多重背包.md | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/problems/背包问题理论基础多重背包.md b/problems/背包问题理论基础多重背包.md index a988db2c..712380f4 100644 --- a/problems/背包问题理论基础多重背包.md +++ b/problems/背包问题理论基础多重背包.md @@ -334,6 +334,64 @@ func Test_multiplePack(t *testing.T) { PASS ``` +TypeScript: + +> 版本一(改变数据源): + +```typescript +function testMultiPack() { + const bagSize: number = 10; + const weightArr: number[] = [1, 3, 4], + valueArr: number[] = [15, 20, 30], + amountArr: number[] = [2, 3, 2]; + for (let i = 0, length = amountArr.length; i < length; i++) { + while (amountArr[i] > 1) { + weightArr.push(weightArr[i]); + valueArr.push(valueArr[i]); + amountArr[i]--; + } + } + const goodsNum: number = weightArr.length; + const dp: number[] = new Array(bagSize + 1).fill(0); + // 遍历物品 + for (let i = 0; i < goodsNum; i++) { + // 遍历背包容量 + for (let j = bagSize; j >= weightArr[i]; j--) { + dp[j] = Math.max(dp[j], dp[j - weightArr[i]] + valueArr[i]); + } + } + console.log(dp); +} +testMultiPack(); +``` + +> 版本二(改变遍历方式): + +```typescript +function testMultiPack() { + const bagSize: number = 10; + const weightArr: number[] = [1, 3, 4], + valueArr: number[] = [15, 20, 30], + amountArr: number[] = [2, 3, 2]; + const goodsNum: number = weightArr.length; + const dp: number[] = new Array(bagSize + 1).fill(0); + // 遍历物品 + for (let i = 0; i < goodsNum; i++) { + // 遍历物品个数 + for (let j = 0; j < amountArr[i]; j++) { + // 遍历背包容量 + for (let k = bagSize; k >= weightArr[i]; k--) { + dp[k] = Math.max(dp[k], dp[k - weightArr[i]] + valueArr[i]); + } + } + } + console.log(dp); +} +testMultiPack(); +``` + + + -----------------------
From 871d96a2f9202504f2f5c754da7404f602a9f073 Mon Sep 17 00:00:00 2001 From: ZongqinWang <1722249371@qq.com> Date: Wed, 11 May 2022 16:48:59 +0800 Subject: [PATCH 11/17] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=200209.=E9=95=BF?= =?UTF-8?q?=E5=BA=A6=E6=9C=80=E5=B0=8F=E7=9A=84=E5=AD=90=E6=95=B0=E7=BB=84?= =?UTF-8?q?.md=20Scala=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0209.长度最小的子数组.md | 48 +++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/problems/0209.长度最小的子数组.md b/problems/0209.长度最小的子数组.md index fd72cf1b..78b8156c 100644 --- a/problems/0209.长度最小的子数组.md +++ b/problems/0209.长度最小的子数组.md @@ -400,6 +400,54 @@ class Solution { } } ``` +Scala: + +滑动窗口: +```scala +object Solution { + def minSubArrayLen(target: Int, nums: Array[Int]): Int = { + var result = Int.MaxValue // 返回结果,默认最大值 + var left = 0 // 慢指针,当sum>=target,向右移动 + var sum = 0 // 窗口值的总和 + for (right <- 0 until nums.length) { + sum += nums(right) + while (sum >= target) { + result = math.min(result, right - left + 1) // 产生新结果 + sum -= nums(left) // 左指针移动,窗口总和减去左指针的值 + left += 1 // 左指针向右移动 + } + } + // 相当于三元运算符,return关键字可以省略 + if (result == Int.MaxValue) 0 else result + } +} +``` + +暴力解法: +```scala +object Solution { + def minSubArrayLen(target: Int, nums: Array[Int]): Int = { + import scala.util.control.Breaks + var res = Int.MaxValue + var subLength = 0 + for (i <- 0 until nums.length) { + var sum = 0 + Breaks.breakable( + for (j <- i until nums.length) { + sum += nums(j) + if (sum >= target) { + subLength = j - i + 1 + res = math.min(subLength, res) + Breaks.break() + } + } + ) + } + // 相当于三元运算符 + if (res == Int.MaxValue) 0 else res + } +} +``` -----------------------
From cb2fea63e7f5e616f697a715b9d523b6ba877308 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 11 May 2022 09:50:47 +0100 Subject: [PATCH 12/17] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=200113.=E8=B7=AF?= =?UTF-8?q?=E5=BE=84=E6=80=BB=E5=92=8CII=20C=E8=AF=AD=E8=A8=80=E8=A7=A3?= =?UTF-8?q?=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0112.路径总和.md | 65 ++++++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/problems/0112.路径总和.md b/problems/0112.路径总和.md index 6433996c..de155b45 100644 --- a/problems/0112.路径总和.md +++ b/problems/0112.路径总和.md @@ -1007,7 +1007,7 @@ func traversal(_ cur: TreeNode?, count: Int) { ``` ## C -0112.路径总和 +> 0112.路径总和 递归法: ```c bool hasPathSum(struct TreeNode* root, int targetSum){ @@ -1062,6 +1062,69 @@ bool hasPathSum(struct TreeNode* root, int targetSum){ return false; } ``` +> 0113.路径总和 II +```c +int** ret; +int* path; +int* colSize; +int retTop; +int pathTop; + +void traversal(const struct TreeNode* const node, int count) { + // 若当前节点为叶子节点 + if(!node->right && !node->left) { + // 若当前path上的节点值总和等于targetSum。 + if(count == 0) { + // 复制当前path + int *curPath = (int*)malloc(sizeof(int) * pathTop); + memcpy(curPath, path, sizeof(int) * pathTop); + // 记录当前path的长度为pathTop + colSize[retTop] = pathTop; + // 将当前path加入到ret数组中 + ret[retTop++] = curPath; + } + return; + } + + // 若节点有左/右孩子 + if(node->left) { + // 将左孩子的值加入path中 + path[pathTop++] = node->left->val; + traversal(node->left, count - node->left->val); + // 回溯 + pathTop--; + } + if(node->right) { + // 将右孩子的值加入path中 + path[pathTop++] = node->right->val; + traversal(node->right, count - node->right->val); + // 回溯 + --pathTop; + } +} + +int** pathSum(struct TreeNode* root, int targetSum, int* returnSize, int** returnColumnSizes){ + // 初始化数组 + ret = (int**)malloc(sizeof(int*) * 1000); + path = (int*)malloc(sizeof(int*) * 1000); + colSize = (int*)malloc(sizeof(int) * 1000); + retTop = pathTop = 0; + *returnSize = 0; + + // 若根节点不存在,返回空的ret + if(!root) + return ret; + // 将根节点加入到path中 + path[pathTop++] = root->val; + traversal(root, targetSum - root->val); + + // 设置返回ret数组大小,以及其中每个一维数组元素的长度 + *returnSize = retTop; + *returnColumnSizes = colSize; + + return ret; +} +``` From c363e9da86973e5dafaa5e765c9c6318b5eb9723 Mon Sep 17 00:00:00 2001 From: Steve2020 <841532108@qq.com> Date: Wed, 11 May 2022 16:59:05 +0800 Subject: [PATCH 13/17] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=EF=BC=880198.=E6=89=93?= =?UTF-8?q?=E5=AE=B6=E5=8A=AB=E8=88=8D.md=EF=BC=89=EF=BC=9A=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0typescript=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0198.打家劫舍.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/problems/0198.打家劫舍.md b/problems/0198.打家劫舍.md index dfe1f3a0..a828b9a9 100644 --- a/problems/0198.打家劫舍.md +++ b/problems/0198.打家劫舍.md @@ -189,6 +189,29 @@ const rob = nums => { }; ``` +TypeScript: + +```typescript +function rob(nums: number[]): number { + /** + dp[i]: 前i个房屋能偷到的最大金额 + dp[0]: nums[0]; + dp[1]: max(nums[0], nums[1]); + ... + dp[i]: max(dp[i-1], dp[i-2]+nums[i]); + */ + const length: number = nums.length; + if (length === 1) return nums[0]; + const dp: number[] = []; + dp[0] = nums[0]; + dp[1] = Math.max(nums[0], nums[1]); + for (let i = 2; i < length; i++) { + dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i]); + } + return dp[length - 1]; +}; +``` + From 296485551542d296e27486e985406d7944f3aa9a Mon Sep 17 00:00:00 2001 From: Steve2020 <841532108@qq.com> Date: Wed, 11 May 2022 18:35:43 +0800 Subject: [PATCH 14/17] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=EF=BC=880213.=E6=89=93?= =?UTF-8?q?=E5=AE=B6=E5=8A=AB=E8=88=8DII.md=EF=BC=89=EF=BC=9A=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0typescript=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0213.打家劫舍II.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/problems/0213.打家劫舍II.md b/problems/0213.打家劫舍II.md index 8e569e46..9e698d01 100644 --- a/problems/0213.打家劫舍II.md +++ b/problems/0213.打家劫舍II.md @@ -165,7 +165,30 @@ const robRange = (nums, start, end) => { return dp[end] } ``` +TypeScript: + +```typescript +function rob(nums: number[]): number { + const length: number = nums.length; + if (length === 0) return 0; + if (length === 1) return nums[0]; + return Math.max(robRange(nums, 0, length - 2), + robRange(nums, 1, length - 1)); +}; +function robRange(nums: number[], start: number, end: number): number { + if (start === end) return nums[start]; + const dp: number[] = []; + dp[start] = nums[start]; + dp[start + 1] = Math.max(nums[start], nums[start + 1]); + for (let i = start + 2; i <= end; i++) { + dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i]); + } + return dp[end]; +} +``` + Go: + ```go // 打家劫舍Ⅱ 动态规划 // 时间复杂度O(n) 空间复杂度O(n) From 5da6c06ef9fd308e9ab77b8393e81377eec75821 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 14 May 2022 16:27:47 +0100 Subject: [PATCH 15/17] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20=E8=83=8C=E5=8C=85?= =?UTF-8?q?=E7=90=86=E8=AE=BA=E8=82=8C=E9=86=8701=E8=83=8C=E5=8C=85=20C?= =?UTF-8?q?=E8=AF=AD=E8=A8=80=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/背包理论基础01背包-1.md | 46 ++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/problems/背包理论基础01背包-1.md b/problems/背包理论基础01背包-1.md index fe940b4c..43ad26be 100644 --- a/problems/背包理论基础01背包-1.md +++ b/problems/背包理论基础01背包-1.md @@ -423,5 +423,51 @@ function test () { test(); ``` +### C +```c +#include +#include +#include + +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#define ARR_SIZE(a) (sizeof((a)) / sizeof((a)[0])) +#define BAG_WEIGHT 4 + +void backPack(int* weights, int weightSize, int* costs, int costSize, int bagWeight) { + // 开辟dp数组 + int dp[weightSize][bagWeight + 1]; + memset(dp, 0, sizeof(int) * weightSize * (bagWeight + 1)); + + int i, j; + // 当背包容量大于物品0的重量时,将物品0放入到背包中 + for(j = weights[0]; j <= bagWeight; ++j) { + dp[0][j] = costs[0]; + } + + // 先遍历物品,再遍历重量 + for(j = 1; j <= bagWeight; ++j) { + for(i = 1; i < weightSize; ++i) { + // 如果当前背包容量小于物品重量 + if(j < weights[i]) + // 背包物品的价值等于背包不放置当前物品时的价值 + dp[i][j] = dp[i-1][j]; + // 若背包当前重量可以放置物品 + else + // 背包的价值等于放置该物品或不放置该物品的最大值 + dp[i][j] = MAX(dp[i - 1][j], dp[i - 1][j - weights[i]] + costs[i]); + } + } + + printf("%d\n", dp[weightSize - 1][bagWeight]); +} + +int main(int argc, char* argv[]) { + int weights[] = {1, 3, 4}; + int costs[] = {15, 20, 30}; + backPack(weights, ARR_SIZE(weights), costs, ARR_SIZE(costs), BAG_WEIGHT); + return 0; +} +``` + -----------------------
From aa22b802a5986f06a123c59f395bf49aba779d1a Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 15 May 2022 14:39:41 +0100 Subject: [PATCH 16/17] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20=E8=83=8C=E5=8C=85?= =?UTF-8?q?=E7=90=86=E8=AE=BA=E5=9F=BA=E7=A1=8001-2.mc=20C=E8=AF=AD?= =?UTF-8?q?=E8=A8=80=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/背包理论基础01背包-2.md | 33 ++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/problems/背包理论基础01背包-2.md b/problems/背包理论基础01背包-2.md index dabdfb2d..a99a872b 100644 --- a/problems/背包理论基础01背包-2.md +++ b/problems/背包理论基础01背包-2.md @@ -315,6 +315,39 @@ function test () { test(); ``` +### C +```c +#include +#include + +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#define ARR_SIZE(arr) ((sizeof((arr))) / sizeof((arr)[0])) +#define BAG_WEIGHT 4 + +void test_back_pack(int* weights, int weightSize, int* values, int valueSize, int bagWeight) { + int dp[bagWeight + 1]; + memset(dp, 0, sizeof(int) * (bagWeight + 1)); + + int i, j; + // 先遍历物品 + for(i = 0; i < weightSize; ++i) { + // 后遍历重量。从后向前遍历 + for(j = bagWeight; j >= weights[i]; --j) { + dp[j] = MAX(dp[j], dp[j - weights[i]] + values[i]); + } + } + + // 打印最优结果 + printf("%d\n", dp[bagWeight]); +} + +int main(int argc, char** argv) { + int weights[] = {1, 3, 4}; + int values[] = {15, 20, 30}; + test_back_pack(weights, ARR_SIZE(weights), values, ARR_SIZE(values), BAG_WEIGHT); + return 0; +} +``` ----------------------- From 19abe18019814af74ee51ba56e4e8ee6106b1253 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 15 May 2022 15:26:23 +0100 Subject: [PATCH 17/17] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=200416.=E5=88=86?= =?UTF-8?q?=E5=89=B2=E7=AD=89=E5=92=8C=E5=AD=90=E9=9B=86.md=20C=E8=AF=AD?= =?UTF-8?q?=E8=A8=80=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0416.分割等和子集.md | 100 ++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/problems/0416.分割等和子集.md b/problems/0416.分割等和子集.md index 6e93ae8e..76cfd87f 100644 --- a/problems/0416.分割等和子集.md +++ b/problems/0416.分割等和子集.md @@ -416,6 +416,106 @@ var canPartition = function(nums) { }; ``` +C: +二维dp: +```c +/** +1. dp数组含义:dp[i][j]为背包重量为j时,从[0-i]元素和最大值 +2. 递推公式:dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - nums[i]] + nums[i]) +3. 初始化:dp[i][0]初始化为0。因为背包重量为0时,不可能放入元素。dp[0][j] = nums[0],当j >= nums[0] && j < target时 +4. 遍历顺序:先遍历物品,再遍历背包 +*/ +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) + +int getSum(int* nums, int numsSize) { + int sum = 0; + + int i; + for(i = 0; i < numsSize; ++i) { + sum += nums[i]; + } + return sum; +} + +bool canPartition(int* nums, int numsSize){ + // 求出元素总和 + int sum = getSum(nums, numsSize); + // 若元素总和为奇数,则不可能得到两个和相等的子数组 + if(sum % 2) + return false; + + // 若子数组的和等于target,则nums可以被分割 + int target = sum / 2; + // 初始化dp数组 + int dp[numsSize][target + 1]; + // dp[j][0]都应被设置为0。因为当背包重量为0时,不可放入元素 + memset(dp, 0, sizeof(int) * numsSize * (target + 1)); + + int i, j; + // 当背包重量j大于nums[0]时,可以在dp[0][j]中放入元素nums[0] + for(j = nums[0]; j <= target; ++j) { + dp[0][j] = nums[0]; + } + + for(i = 1; i < numsSize; ++i) { + for(j = 1; j <= target; ++j) { + // 若当前背包重量j小于nums[i],则其值等于只考虑0到i-1物品时的值 + if(j < nums[i]) + dp[i][j] = dp[i - 1][j]; + // 否则,背包重量等于在背包中放入num[i]/不放入nums[i]的较大值 + else + dp[i][j] = MAX(dp[i - 1][j], dp[i - 1][j - nums[i]] + nums[i]); + } + } + // 判断背包重量为target,且考虑到所有物品时,放入的元素和是否等于target + return dp[numsSize - 1][target] == target; +} +``` +滚动数组: +```c +/** +1. dp数组含义:dp[j]为背包重量为j时,其中可放入元素的最大值 +2. 递推公式:dp[j] = max(dp[j], dp[j - nums[i]] + nums[i]) +3. 初始化:均初始化为0即可 +4. 遍历顺序:先遍历物品,再后序遍历背包 +*/ +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) + +int getSum(int* nums, int numsSize) { + int sum = 0; + + int i; + for(i = 0; i < numsSize; ++i) { + sum += nums[i]; + } + return sum; +} + +bool canPartition(int* nums, int numsSize){ + // 求出元素总和 + int sum = getSum(nums, numsSize); + // 若元素总和为奇数,则不可能得到两个和相等的子数组 + if(sum % 2) + return false; + // 背包容量 + int target = sum / 2; + + // 初始化dp数组,元素均为0 + int dp[target + 1]; + memset(dp, 0, sizeof(int) * (target + 1)); + + int i, j; + // 先遍历物品,后遍历背包 + for(i = 0; i < numsSize; ++i) { + for(j = target; j >= nums[i]; --j) { + dp[j] = MAX(dp[j], dp[j - nums[i]] + nums[i]); + } + } + + // 查看背包容量为target时,元素总和是否等于target + return dp[target] == target; +} +```