mirror of
https://github.com/youngyangyang04/leetcode-master.git
synced 2025-07-09 03:34:02 +08:00
Merge pull request #1302 from KingArthur0205/master
添加 0112.路径总和.md, 背包理论基础01背包.md, 0416.分割等和子集.md C语言解法
This commit is contained in:
@ -1006,6 +1006,126 @@ 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;
|
||||
}
|
||||
```
|
||||
> 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;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
-----------------------
|
||||
|
@ -416,6 +416,108 @@ 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;
|
||||
}
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
> 一维数组,简洁
|
||||
|
@ -432,6 +432,54 @@ function test () {
|
||||
test();
|
||||
```
|
||||
|
||||
|
||||
### C
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### TypeScript
|
||||
|
||||
```typescript
|
||||
|
@ -317,6 +317,40 @@ function test () {
|
||||
test();
|
||||
```
|
||||
|
||||
### C
|
||||
```c
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
```
|
||||
|
||||
### TypeScript
|
||||
|
||||
```typescript
|
||||
|
Reference in New Issue
Block a user