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

代码随想录第23天|回溯part3 组合与分割

39.组合总和

在这里插入图片描述

class Solution {
public:vector<vector<int>> res;vector<int> path;void backTracking(vector<int>& candidates,int target,int sum,int n,int step){if(n > 150) return;if(sum > target) return;if(sum == target){res.push_back(path);return;}for(int i = step; i < candidates.size(); i++){path.push_back(candidates[i]);backTracking(candidates,target,sum+candidates[i],n+1,i);path.pop_back();}}vector<vector<int>> combinationSum(vector<int>& candidates, int target) {backTracking(candidates,target,0,0,0);return res;}
};

40.组合总和2

在这里插入图片描述
难题
在这里插入图片描述
可以看出在candidates[i] == candidates[i - 1]相同的情况下:
used[i - 1] == true,说明同一树枝candidates[i - 1]使用过
used[i - 1] == false,说明同一树层candidates[i - 1]使用过
因为同一树层,used[i - 1] == false 才能表示,当前取的 candidates[i] 是从 candidates[i - 1] 回溯而来的。
而 used[i - 1] == true,说明是进入下一层递归,去下一个数,所以是树枝上

即:因为在排序后,相同的数都会挨在一起,如果当前数和上个数相同的话,那么在递归的过程中,如果上一个数没被用到,那么当前数肯定是一种重复的情况,因为这两个数相同,肯定是先使用前一个数的,而如果上一个没用到,则表示是已经递归过上一个数的所有情况并回溯了,现在递归下一个数的,所以需要跳过重复的这个数。

class Solution {
public:vector<vector<int>> res;vector<int> path;bool used[101];void backTracking(vector<int>& candidates, int target, int sum, int step) {if (sum == target) {res.push_back(path);return;}for (int i = step; i < candidates.size(); i++) {if (sum + candidates[i] > target)break;if (i > 0 && used[i - 1] == false &&candidates[i] == candidates[i - 1])continue;path.push_back(candidates[i]);used[i] = true;backTracking(candidates, target, sum + candidates[i], i + 1);used[i] = false;path.pop_back();}}vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {sort(candidates.begin(), candidates.end());backTracking(candidates, target, 0, 0);return res;}
};

也可以直接使用startIndex来去重,每层递归里,如果一个数和上一个数相同,则跳过

void backtracking(vector<int>& candidates, int target, int sum, int startIndex) {if (sum == target) {result.push_back(path);return;}for (int i = startIndex; i < candidates.size() && sum + candidates[i] <= target; i++) {// 要对同一树层使用过的元素进行跳过// 这里i > startIndex是为了确保可以选取到同一种元素,在下层递归的时候,因为传入的是i+1,所以如果i+1和上一个元素相同,递归后也可以选取和i相同的元素if (i > startIndex && candidates[i] == candidates[i - 1]) {continue;}sum += candidates[i];path.push_back(candidates[i]);backtracking(candidates, target, sum, i + 1); // 和39.组合总和的区别1,这里是i+1,每个数字在每个组合中只能使用一次sum -= candidates[i];path.pop_back();}}

131.分割回文串

在这里插入图片描述
回溯三步
1.递归函数确定参数:string s, int step
2.确定终止条件:因为分割串类似于组合问题,
例如对于字符串abcdef:
组合问题:选取一个a之后,在bcdef中再去选取第二个,选取b之后在cdef中再选取第三个…。
切割问题:切割一个a之后,在bcdef中再去切割第二段,切割b之后在cdef中再切割第三段…。
在这里插入图片描述
返回条件就是,当切割点超过串的长度时,说明已经找到一种每个字串都是回文串的方案了,这个时候就可以把字串数组传给结果
3.确定单层逻辑
单层逻辑就是树的横向遍历,即用for循环确定切割点,且切割点必须不断往后

class Solution {
public:vector<vector<string>> res;vector<string> path;bool check(string t) {for (int i = 0, j = t.size() - 1; i < j; i++, j--) {if (t[i] != t[j])return false;}return true;}void backTracking(string s, int step) {if (step >= s.size()) {// 如果大于数组长度,则找到一组全为回文串的字串组合,否则被continue掉了res.push_back(path);return;}for (int i = step; i < s.size(); i++) {// 截取字串string t = s.substr(step, i - step + 1);// 找到了符合条件的字串if (check(t))path.push_back(t);elsecontinue;// 进行下一层递归backTracking(s, i + 1);path.pop_back();}}vector<vector<string>> partition(string s) {backTracking(s, 0);return res;}
};

最近在学go,所以提供一个go版本的代码

var res [][]string
var path []stringfunc check(t string) bool {for i, j := 0, len(t)-1; i < j; i, j = i+1, j-1 {if t[i] != t[j] {return false}}return true
}
func backTracking(s string, step int) {if step >= len(s) {temp := make([]string, len(path))copy(temp, path)res = append(res, temp)return}for i := step; i < len(s); i++ {t := s[step : i+1]if check(t) {path = append(path, t)} else {continue}backTracking(s, i+1)path = path[:len(path)-1]}
}
func partition(s string) [][]string {path = make([]string, 0)res = make([][]string, 0)backTracking(s, 0)return res
}

相关文章:

  • 微服务学习Day8-Sentinel
  • Flink搭建
  • 【LeetCode】二叉树oj专题
  • elementplu父级页面怎么使用封装子组件原组件的方法
  • 【距离四六级只剩一个星期!】刘晓艳四级保命班课程笔记(2)(可分享治资料~)
  • 前端 html格式转md格式插件使用介绍
  • 解决JSON.stringify 方法在序列化 BigInt 类型时的错误
  • ardupilot开发 --- 机载计算机-软件方案 篇
  • 基于单片机的超声波倒车雷达设计
  • 汇舟问卷:国外问卷调查怎么样?
  • mysql like 查询优化
  • 遥感卫星影像处理流程
  • 3403(3519Dv500)算子精度比对工具标杆数据生成环境搭建指导(Caffe)
  • 【Python Cookbook】S01E15 将名称映射到序列的元素中
  • Next.js API Routes:构建服务端功能
  • [译] 理解数组在 PHP 内部的实现(给PHP开发者的PHP源码-第四部分)
  • 《深入 React 技术栈》
  • spring + angular 实现导出excel
  • VUE es6技巧写法(持续更新中~~~)
  • Vue2.0 实现互斥
  • 百度贴吧爬虫node+vue baidu_tieba_crawler
  • 区块链共识机制优缺点对比都是什么
  • 我的面试准备过程--容器(更新中)
  • 一天一个设计模式之JS实现——适配器模式
  • 3月7日云栖精选夜读 | RSA 2019安全大会:企业资产管理成行业新风向标,云上安全占绝对优势 ...
  • 浅谈sql中的in与not in,exists与not exists的区别
  • #laravel 通过手动安装依赖PHPExcel#
  • #我与虚拟机的故事#连载20:周志明虚拟机第 3 版:到底值不值得买?
  • ( 10 )MySQL中的外键
  • (7)STL算法之交换赋值
  • (C#)获取字符编码的类
  • (env: Windows,mp,1.06.2308310; lib: 3.2.4) uniapp微信小程序
  • (非本人原创)史记·柴静列传(r4笔记第65天)
  • (附源码)springboot宠物管理系统 毕业设计 121654
  • (十五)devops持续集成开发——jenkins流水线构建策略配置及触发器的使用
  • (一一四)第九章编程练习
  • (原創) 博客園正式支援VHDL語法著色功能 (SOC) (VHDL)
  • (原創) 系統分析和系統設計有什麼差別? (OO)
  • (转载)跟我一起学习VIM - The Life Changing Editor
  • .mp4格式的视频为何不能通过video标签在chrome浏览器中播放?
  • .NET 8.0 中有哪些新的变化?
  • .net core 连接数据库,通过数据库生成Modell
  • .Net mvc总结
  • .net 调用海康SDK以及常见的坑解释
  • .NET 发展历程
  • .NET 直连SAP HANA数据库
  • .NET+WPF 桌面快速启动工具 GeekDesk
  • .NET导入Excel数据
  • .net开发日常笔记(持续更新)
  • .Net下C#针对Excel开发控件汇总(ClosedXML,EPPlus,NPOI)
  • .vue文件怎么使用_我在项目中是这样配置Vue的
  • //TODO 注释的作用
  • :如何用SQL脚本保存存储过程返回的结果集
  • @Controller和@RestController的区别?
  • @data注解_SpringBoot 使用WebSocket打造在线聊天室(基于注解)