当前位置: 首页 > backend >正文

LeeCode 40.组合总和II

给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

candidates 中的每个数字在每个组合中只能使用 一次 。

注意:解集不能包含重复的组合。 

示例 1:

输入: candidates = [10,1,2,7,6,1,5], target = 8,
输出:
[
[1,1,6],
[1,2,5],
[1,7],
[2,6]
]

示例 2:

输入: candidates = [2,5,2,1,2], target = 5,
输出:
[
[1,2,2],
[5]
]

提示:

  • 1 <= candidates.length <= 100
  • 1 <= candidates[i] <= 50
  • 1 <= target <= 30

答案如下:

void zuhe2(int target, int idx, int* temp, int tempSize, int** res, int*** pRes, int* returnSize, int** returnColumnSizes, int* pCapacity, int* numCountMap);/*** Return an array of arrays of size *returnSize.* The sizes of the arrays are returned as *returnColumnSizes array.* Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().*/
int** combinationSum2(int* candidates, int candidatesSize, int target, int* returnSize, int** returnColumnSizes) { // LeetCode 40.组合和总和// 先统计数组中每个数的出现个数。由题意 1 <= candidates[i] <= 50, numCountMap[n]表示n在candidates数组中出现的次数int numCountMap[51] = { 0 };for (int i = 0; i < candidatesSize; i++) {numCountMap[candidates[i]]++;}// 1 <= target <= 30 , 而数组candidates中的数最小为1,所以组合子数组长度最大可能为30// 但是不知道组合数量,所以结果数组大小不确定。int tempCapacity = candidatesSize < 30 ? candidatesSize : 30;int* temp = (int*)malloc(tempCapacity * sizeof(int)); if (!temp) return NULL;*returnSize = 0;int capacity = 2; // 初始容量,后续容量不够再扩容*returnColumnSizes = (int*)malloc(capacity * sizeof(int));int** res = (int**)malloc(capacity * sizeof(int*));if (!res) return NULL;zuhe2(target, 0, temp, 0, res ,&res ,returnSize, returnColumnSizes, &capacity, numCountMap);free(temp);return res;
}void zuhe2(int target, int idx, int* temp, int tempSize, int** res, int*** pRes, int* returnSize, int** returnColumnSizes, int* pCapacity, int* numCountMap) {if (target == 0) {// 已满足,保存结果int* arr_ = (int*)malloc(tempSize * sizeof(int));if (!arr_) return;memcpy(arr_, temp, tempSize * sizeof(int));// 保存前先检查容量if (*returnSize == *pCapacity) { // 之前申请的内存满了,不够再存储了,扩容int newCapacity = *pCapacity << 1;int** temp_res = (int**)realloc(res, newCapacity * sizeof(int*));if (!temp_res) return;*pRes = temp_res;*returnColumnSizes = (int*)realloc(*returnColumnSizes, newCapacity * sizeof(int));if (*returnColumnSizes == NULL) return;*pCapacity = newCapacity;}*(*pRes + *returnSize) = arr_;*(*returnColumnSizes + *returnSize) = tempSize; // 该组合的数字个数*returnSize = *returnSize + 1;return;}for (int i = idx; i < 51; i++) {// 先判断i是否使用过了if (numCountMap[i] == 0) {// 该数使用完了continue;}if (i > target) {break;}// 可以加的情况,选中该数temp[tempSize++] = i;numCountMap[i]--;// 再递归选给临时数组下一位赋值。 注意,这里idx参数值必选传i,不能传idx,防止选到重复的组合。组合的临时数组中当前在选的数还可以选,但前面选过的数不能再选zuhe2(target - i, i, temp, tempSize, res, pRes, returnSize, returnColumnSizes, pCapacity, numCountMap);// 回退,不选这个数了tempSize--;numCountMap[i]++;}
}

测试代码:

void testLeeCode40(void) { // 组合总和IIint nums[] = { 4,4,2,1,4,2,2,1,3 };int target = 6;int numsSize = sizeof(nums) / sizeof(int);int returnSize; // 用于接受结果二维数组的长度。int* returnColumnSizes; // 用来接受结果二维数组的每个元素(即子数组)的长度int** res = combinationSum2(nums, numsSize, target, &returnSize, &returnColumnSizes);printArr(res, returnSize, returnColumnSizes); // 打印二维数组// 释放内存for (int i = 0; i < returnSize; i++) {free(res[i]);}free(res);free(returnColumnSizes);
}

运行:

ok.  但是提交到LeeCode,报错:

看上去是调用realloc函数时报错重复释放内存了。  但是没看出来哪里重复释放内存了。没懂这个报错哪来的,我自己机器上没报错。怎么办? 我把二维数组的容量直接设置为1000,1000应该是够用了,避免了动态扩容数组,提交通过了:

这个疑问点后面再研究。

http://www.xdnf.cn/news/18448.html

相关文章:

  • SpringBoot -- 集成Spring Security (二)
  • CTFSHOW | 其他篇题解(二)web417 - web437
  • LeetCode第55题 - 跳跃游戏
  • 学习游戏制作记录(合成表UI和技能树的UI)8.22
  • SpringBoot项目创建的五种方式
  • 53 C++ 现代C++编程艺术2-枚举和枚举类
  • C++ unistd.h库文件介绍(文件与目录操作, 进程管理, 系统环境访问, 底层I/O操作, 系统休眠/执行控制)
  • Linux服务测试
  • 【链表 - LeetCode】24. 两两交换链表中的节点
  • 深入理解 Java IO 流 —— 从入门到实战
  • 排序(数据结构)
  • nanoGPT 部署
  • JUC之Fork/Join
  • EP4CE40F23I7N Altera FPGA Cyclone IV E
  • LLM实践系列:利用LLM重构数据科学流程
  • shell脚本第二阶段-----选择结构
  • 企业设备系统选型:功能适配度分析
  • Vue 插槽(Slots)全解析1
  • B树,B+树,B*树
  • 文件包含的学习笔记
  • 嵌入式Linux学习 -- 网络1
  • 深度学习——神经网络
  • canvas绘制图片等比缩放
  • Vue2+Vue3前端开发_Day6
  • Linux笔记8——shell编程基础-2
  • 网络实践——Socket编程UDP
  • 视频拼接融合技术:打造全景视界的革命性产品
  • API模型与接口弃用指南:历史、替代方案及开发者应对策略
  • `git mv` 重命名 Git 仓库中的文件夹
  • 多人编程新方式:cpolar 让 OpenHands 远程开发更轻松