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

LeetCode 刷题【40. 组合总和 II】

40. 组合总和 II

自己做

解:递归选取(超内存)

class Solution {
public:void dfs(vector<int> &candidates,int target, vector<vector<int>> &res, vector<int> old_combination, vector<int>::iterator idx){        //old_combination是当前组合,res是保存的结果,idx为当前下标索引//如果idx等于candidates.end(),说明后面也找不到了,都结束了if(idx == candidates.end())return;//太好了,当前元素就是我们要找的组合中最后一个元素,将其加入结果中if(target == *idx){old_combination.push_back(*idx);                //加入组合中//检查该组合是否已经存在于结果中bool exist = false;int r_len = res.size();for(int i = 0; i < r_len; i++)if(res[i].size() == old_combination.size()){        //如果两种组合的长度一致,则有可能重复;长度不一致,必然不重复int c_len = old_combination.size();bool equal = true;for(int j = 0; j < c_len; j++)if(res[i][j] != old_combination[j]){          //存在不一致equal = false;break;}if(equal)                      //如果经过上面的查找发现完全一致【equal不更改为false】,则标记存在重复组合exist = true;}if(!exist)                          //不存在重复组合则存放res.push_back(old_combination);                 //将组合放入结果}//不是我们要找的,或者至少现在不是else if(target > *idx){       //比当前大(能继续减去当前元素),往下继续找,否则结束递归//不选取的情况,直接继续往后找dfs(candidates, target, res, old_combination, idx + 1);//选取的情况,这里的将target与当前值相减【这就相当于target减去组合中所有值的和】old_combination.push_back(*idx);//开始递归dfs(candidates, target - *idx, res, old_combination, idx + 1);}//如果是target < candidate就说明,后面都找不到了直接结束(这里candidate是升序排序)}vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {vector<vector<int>> res;int len = candidates.size();int sum = 0;for(int i = 0; i < len; i++)sum += candidates[i];if(target > sum)            //将全部数加起来都没有target大,后面不用看了,直接返回return res;sort(candidates.begin(),candidates.end());                //排序dfs(candidates, target, res, vector<int>(), candidates.begin());         //递归return res;}
};

看题解

40. 组合总和 II - 力扣(LeetCode)

大佬代码

这里进行递归时,每一轮选取元素时,会对比所有元素进行添加,而且通过if (i > start && choices[i] == choices[i - 1])判断元素是否出现重复,如果重复了就跳过(保证通过i选取的元素是不重复的),要想选重复元素只能通过递归backtrack(state, target - choices[i], choices, i + 1, res)选取,这样选取重复元素时就是连着取了,不可能出现跳着取的情况,这样就避免了子集的重复

class Solution {
public:vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {vector<int> state;              // 状态(子集)sort(candidates.begin(), candidates.end()); // 对 candidates 进行排序int start = 0;                  // 遍历起始点vector<vector<int>> res;        // 结果列表(子集列表)backtrack(state, target, candidates, start, res);return res;}
private:void backtrack(vector<int> &state, int target, vector<int> &choices, int start, vector<vector<int>> &res) {// 子集和等于 target 时,记录解if (target == 0) {res.push_back(state);return;}// 遍历所有选择// 剪枝二:从 start 开始遍历,避免生成重复子集// 剪枝三:从 start 开始遍历,避免重复选择同一元素for (int i = start; i < choices.size(); i++) {// 剪枝一:若子集和超过 target ,则直接结束循环// 这是因为数组已排序,后边元素更大,子集和一定超过 targetif (target - choices[i] < 0) {break;}// 剪枝四:如果该元素与左边元素相等,说明该搜索分支重复,直接跳过if (i > start && choices[i] == choices[i - 1]) {continue;}// 尝试:做出选择,更新 target, startstate.push_back(choices[i]);// 进行下一轮选择backtrack(state, target - choices[i], choices, i + 1, res);// 回退:撤销选择,恢复到之前的状态state.pop_back();}}
};
http://www.xdnf.cn/news/17866.html

相关文章:

  • 基于C#、.net、asp.net的心理健康咨询系统设计与实现/心理辅导系统设计与实现
  • 药房智能盘库系统的Python编程分析与实现—基于计算机视觉与时间序列预测的智能库存管理方案
  • Redis学习——Redis的十大类型String、List、Hash、Set、Zset
  • 仓库无人叉车的安全功能有哪些?如何在提升效率时保障安全?
  • 机器学习——svm支持向量机
  • 为什么要使用消息队列呢?
  • 【龙泽科技】汽车故障诊断仿真教学软件【科鲁兹】
  • 总经理掌舵研发团队:在技术突破与商业落地间找到平衡的艺术-中小企实战运营和营销工作室博客
  • 力扣 hot100 Day72
  • Gradle(二)Gradle的优势、项目结构介绍
  • LINUX812 shell脚本:if else,for 判断素数,创建用户
  • Spring Boot项目中调用第三方接口
  • B站 韩顺平 笔记 (Day 16)
  • 终端安全与网络威胁防护笔记
  • 秋招笔记-8.12
  • Web 安全之互联网暴露面管理
  • 计算机网络2-3:传输方式
  • 赛灵思ZYNQ官方文档UG585自学翻译笔记:UART Controller,通用异步收发传输器控制器
  • C语言中关于普通变量和指针变量、结构体包含子结构体或包含结构体指针的一些思考
  • windows单机单卡+CIFAR-10数据集+Docker模拟训练
  • 一键设置 NTP 时区的脚本(亲测,适用于部署 K8S 的前置环境)
  • http网页部署
  • 【从零开始java学习|第四篇】IntelliJ IDEA 入门指南
  • C++方向知识汇总(四)
  • Ansible 自动化介绍
  • 如何在idea中导入外来文件
  • 基于大数据的在线教育评估系统 Python+Django+Vue.js
  • C++中template、 implicit 、explicit关键字详解
  • Rust 项目编译故障排查:从 ‘onnxruntime‘ 链接失败到 ‘#![feature]‘ 工具链不兼容错误
  • Rust:构造函数 new() 如何进行错误处理?