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

算法刷题Day27 | 39. 组合总和、40.组合总和II、131.分割回文串

目录

  • 0 引言
  • 1 组合总和
    • 1.1 我的解题
  • 2 组合总和II
    • 2.1 解题
  • 3 分割回文串
    • 3.1 切割
    • 3.2 总结:分割和组合的区别

请添加图片描述

  • 🙋‍♂️ 作者:海码007
  • 📜 专栏:算法专栏
  • 💥 标题:算法刷题Day27 | 39. 组合总和、40.组合总和II、131.分割回文串
  • ❣️ 寄语:书到用时方恨少,事非经过不知难!

0 引言

趁着周末赶紧追

1 组合总和

  • 🎈 文档讲解
  • 🎈 视频讲解
  • 🎈 做题状态:

1.1 我的解题

这道题其实就是可以把已经遍历的元素再遍历一次,就是改变了 firstIndex 的位置而已。逻辑和之前的题目类似。还有终止条件不太一样就是。

class Solution
{
public:// 1. 回溯函数参数和返回值void backTracing(vector<int>& candidates, int target, int firstIndex, vector<int>& path, vector<vector<int>>& paths){// 2. 终止条件int sum = 0;for (auto data : path){sum += data;}if (sum > target){return;}if (sum == target){paths.emplace_back(path);return;}// 3. 单层回溯逻辑for (int i = firstIndex; i < candidates.size(); i++){path.emplace_back(candidates[i]);backTracing(candidates, target, i, path, paths);path.pop_back();}}vector<vector<int>> combinationSum(vector<int>& candidates, int target) {vector<vector<int>> paths;vector<int> path;backTracing(candidates, target, 0, path, paths);return paths;}};

2 组合总和II

  • 🎈 文档讲解
  • 🎈 视频讲解
  • 🎈 做题状态:

2.1 解题

这道题注意了,集合中不能有重复的。上一道题简单的改变 firstIndex 就可以避免重复的组合是因为,给出的集合中本身不含有重复的数字。但是这道题中是包含重复数字的。

这道题比较难,理解关键点在于 去重:树层去重、树枝去重。

那么如何判断当前是同一层还是树枝呢?使用一个额外的 used 数组来标识。

详细的解释参考文档。

class Solution {
private:vector<vector<int>> result;vector<int> path;void backtracking(vector<int>& candidates, int target, int sum, int startIndex, vector<bool>& used) {if (sum == target) {result.push_back(path);return;}for (int i = startIndex; i < candidates.size() && sum + candidates[i] <= target; i++) {// used[i - 1] == true,说明同一树枝candidates[i - 1]使用过// used[i - 1] == false,说明同一树层candidates[i - 1]使用过// 要对同一树层使用过的元素进行跳过if (i > 0 && candidates[i] == candidates[i - 1] && used[i - 1] == false) {continue;}sum += candidates[i];path.push_back(candidates[i]);used[i] = true;backtracking(candidates, target, sum, i + 1, used); // 和39.组合总和的区别1,这里是i+1,每个数字在每个组合中只能使用一次used[i] = false;sum -= candidates[i];path.pop_back();}}public:vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {vector<bool> used(candidates.size(), false);path.clear();result.clear();// 首先把给candidates排序,让其相同的元素都挨在一起。sort(candidates.begin(), candidates.end());backtracking(candidates, target, 0, 0, used);return result;}
};

3 分割回文串

  • 🎈 文档讲解
  • 🎈 视频讲解
  • 🎈 做题状态:

3.1 切割

使用回溯进行切割是如何进行的呢? 如何切割是回溯的一种经典题目了。

犀利糊涂写出来了,有一个疑惑的地方,在判断当前子串不是回文串时,为什么是进入下一个循环而不是跳出所有循环。

因为同一个循环内是同一层,加入当前层的前面有一个节点不满足,直接break的话,后面满足的节点也会被去除。所以应该使用continue。continue是跳过当前的节点,也就是说以这个节点为根的所有结果肯定都是不满足的。

class Solution {
public:// 判断是否是回文串bool isPalindrome(string s){for (int i = 0; i < s.size()/2; i++){if (s[i] != s[s.size() - 1 - i]){return false;}}return true;}// 回溯 (startIndex从0开始)void backTracing(string& s, int startIndex, vector<string>& path, vector<vector<string>>& paths){// 终止条件if (startIndex == s.size()){paths.emplace_back(path);return;}// 单层回溯逻辑for (int i = startIndex; i < s.size(); i++){string tmp = s.substr(startIndex, i - startIndex + 1);if (isPalindrome(tmp)){path.emplace_back(tmp);backTracing(s, i + 1, path, paths);path.pop_back();}else{continue;	// 注意是continue ,而不是break}}}vector<vector<string>> partition(string s) {vector<string> path;vector<vector<string>> paths;backTracing(s, 0, path, paths);return paths;}
};

3.2 总结:分割和组合的区别

分割和组合的区别:组合是每次选取一个元素出来然后加入到path数组中。而分割就是取一个区间的元素出来,然后加入到path数组中;

那么分割区间的数据如何获取呢?根据当期遍历的 i 和 startIndex 就可以进行确定。
string tmp = s.substr(startIndex, i - startIndex + 1); 这个就是把区间中的字符串获取出来。

相关文章:

  • FastGpt流程
  • Redis 持久化个人总结
  • 【算法】两数之和(暴力求解+哈希表)
  • 用tkinter来实现扫雷游戏
  • usb_camera传输视频流编码的问题记录!
  • Elasticsearch 聚合函数返回空数组|查询返回空内容 rs里有数据
  • 海康Ehome2.0与5.0设备接入EasyCVR视频汇聚平台时的配置区别
  • 穿越代码之海:探寻结构体深层逻辑,展望未来应用新天地
  • webpack环境配置分类结合vue使用
  • 蓝桥杯算法题:最大比例
  • 金融企业区域集中库的设计构想和测试验证
  • kubeadm部署的k8s1.29集群证书更新
  • 微信小程序中实现埋点的方法
  • flink1.18源码本地调试环境
  • 如何操作RAID 0阵列的扩容?
  • ES6 学习笔记(一)let,const和解构赋值
  • happypack两次报错的问题
  • JavaScript创建对象的四种方式
  • Java超时控制的实现
  • js对象的深浅拷贝
  • JS实现简单的MVC模式开发小游戏
  • js作用域和this的理解
  • redis学习笔记(三):列表、集合、有序集合
  • Wamp集成环境 添加PHP的新版本
  • 初探 Vue 生命周期和钩子函数
  • 从零开始的无人驾驶 1
  • 简单实现一个textarea自适应高度
  • 聊一聊前端的监控
  • 入门级的git使用指北
  • 提升用户体验的利器——使用Vue-Occupy实现占位效果
  • 微信小程序实战练习(仿五洲到家微信版)
  • 一个完整Java Web项目背后的密码
  • 用Visual Studio开发以太坊智能合约
  • ionic异常记录
  • Java总结 - String - 这篇请使劲喷我
  • ​Kaggle X光肺炎检测比赛第二名方案解析 | CVPR 2020 Workshop
  • ​一帧图像的Android之旅 :应用的首个绘制请求
  • ###51单片机学习(2)-----如何通过C语言运用延时函数设计LED流水灯
  • #《AI中文版》V3 第 1 章 概述
  • #ifdef 的技巧用法
  • #微信小程序:微信小程序常见的配置传值
  • #周末课堂# 【Linux + JVM + Mysql高级性能优化班】(火热报名中~~~)
  • %@ page import=%的用法
  • (14)目标检测_SSD训练代码基于pytorch搭建代码
  • (ibm)Java 语言的 XPath API
  • (pojstep1.3.1)1017(构造法模拟)
  • (博弈 sg入门)kiki's game -- hdu -- 2147
  • (删)Java线程同步实现一:synchronzied和wait()/notify()
  • (十八)devops持续集成开发——使用docker安装部署jenkins流水线服务
  • (十三)Flask之特殊装饰器详解
  • (已解决)vue+element-ui实现个人中心,仿照原神
  • (转) ns2/nam与nam实现相关的文件
  • (转载)OpenStack Hacker养成指南
  • (转载)PyTorch代码规范最佳实践和样式指南
  • .NET Core、DNX、DNU、DNVM、MVC6学习资料