算法训练营 day30 回溯算法 组合总和 组合总和II 分割回文串

news2024/11/15 12:10:01

算法训练营 day30 回溯算法 组合总和 组合总和II 分割回文串

组合总和

39. 组合总和 - 力扣(LeetCode)

给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。

candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。

对于给定的输入,保证和为 target 的不同组合数少于 150 个。

  • 递归函数参数

这里依然是定义两个全局变量,二维数组result存放结果集,数组path存放符合条件的结果。(这两个变量可以作为函数参数传入)

首先是题目中给出的参数,集合candidates, 和目标值target。

  • 递归终止条件

在如下树形结构中:

在这里插入图片描述

从叶子节点可以清晰看到,终止只有两种情况,sum大于target和sum等于target。

sum等于target的时候,需要收集结果

  • 单层搜索的逻辑

单层for循环依然是从startIndex开始,搜索candidates集合。

代码如下:

class Solution {
    List<List<Integer>> result = new ArrayList<List<Integer>>();
    List<Integer> path = new ArrayList<Integer>();

    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        backtracking(candidates, target, 0, 0);
        return result;
    }

    private void backtracking(int[] candidates, int target, int sum, int index) {
        if (sum > target) {
            return;
        }
        if (sum == target) {
            result.add(new ArrayList<>(path));
        }
        for (int i = index; i < candidates.length; i++) {
            path.add(candidates[i]);
            sum += candidates[i];
            backtracking(candidates, target, sum, i);// 不用i+1了,表示可以重复读取当前的数
            sum -= candidates[i];
            path.remove(path.size() - 1);
        }
    }
}

剪枝操作

class Solution {
    List<List<Integer>> result = new ArrayList<List<Integer>>();
    List<Integer> path = new ArrayList<Integer>();

    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        Arrays.sort(candidates);// 先进行排序
        backtracking(candidates, target, 0, 0);
        return result;
    }

    private void backtracking(int[] candidates, int target, int sum, int index) {
        if (sum == target) {
            result.add(new ArrayList<>(path));
        }
        // 如果 sum + candidates[i] > target 就终止遍历
        for (int i = index; i < candidates.length&&sum+candidates[i]<=target; i++) {
            path.add(candidates[i]);
            sum += candidates[i];
            backtracking(candidates, target, sum, i);
            sum -= candidates[i];
            path.remove(path.size() - 1);
        }
    }
}

组合总和II

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

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

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

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

本题的难点在于区别2中:集合(数组candidates)有重复元素,但还不能有重复的组合

回看一下题目,元素在同一个组合内是可以重复的,怎么重复都没事,但两个组合不能相同。

所以我们要去重的是同一树层上的“使用过”,同一树枝上的都是一个组合里的元素,不用去重

为了理解去重我们来举一个例子,candidates = [1, 1, 2], target = 3,(方便起见candidates已经排序了)

强调一下,树层去重的话,需要对数组排序!

选择过程树形结构如图所示:

在这里插入图片描述

  • 递归函数参数

与39.组合总和 (opens new window)套路相同,此题还需要加一个bool型数组used,用来记录同一树枝上的元素是否使用过。

这个集合去重的重任就是used来完成的。

  • 递归终止条件

与39.组合总和 (opens new window)相同,终止条件为 sum > targetsum == target

  • 单层搜索的逻辑

这里与39.组合总和 (opens new window)最大的不同就是要去重了。

前面我们提到:要去重的是“同一树层上的使用过”,如何判断同一树层上元素(相同的元素)是否使用过了呢。

如果candidates[i] == candidates[i - 1] 并且 used[i - 1] == false,就说明:前一个树枝,使用了candidates[i - 1],也就是说同一树层使用过candidates[i - 1]

此时for循环里就应该做continue的操作。

这块比较抽象,如图:

在这里插入图片描述

代码如下:

    List<List<Integer>> result = new ArrayList<List<Integer>>();
    List<Integer> path = new ArrayList<Integer>();

    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        boolean[] used = new boolean[candidates.length];
        Arrays.fill(used,false);
        Arrays.sort(candidates);
        backtracking(candidates, target, 0, 0,used);
        return result;
    }

    private void backtracking(int[] candidates, int target, int sum, int startIndex,boolean[] used) {
        if (sum > target) {
            return;
        }
        if (sum == target) {
            result.add(new ArrayList<>(path));
        }
        for (int i = startIndex; i < candidates.length&&sum+candidates[i]<=target; i++) {

            if (i>0&&candidates[i]==candidates[i-1]&&!used[i-1]){
                continue;
            }
            used[i] = true;
            path.add(candidates[i]);
            sum += candidates[i];
            backtracking(candidates, target, sum, i+1,used);
            sum -= candidates[i];
            path.remove(path.size() - 1);
            used[i] = false;
        }
    }

分割回文串

131. 分割回文串 - 力扣(LeetCode)

给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是 回文串 。返回 s 所有可能的分割方案。

回文串 是正着读和反着读都一样的字符串。

两个主要难点

  1. 切割问题,有不同的切割方式
  2. 判断回文

切割问题,也可以抽象为一棵树形结构,如图:

在这里插入图片描述

  • 递归函数参数

全局变量数组path存放切割后回文的子串,数组result存放结果集。 (这两个参数可以放到函数参数里)

本题递归函数参数还需要startIndex,因为切割过的地方,不能重复切割,和组合问题也是保持一致的。

  • 递归函数终止条件

从树形结构的图中可以看出:切割线切到了字符串最后面,说明找到了一种切割方法,此时就是本层递归的终止条件。

  • 单层搜索的逻辑

来看看在递归循环中如何截取子串呢?

for (int i = startIndex; i < s.size(); i++)循环中,我们 定义了起始位置startIndex,那么 [startIndex, i] 就是要截取的子串。

首先判断这个子串是不是回文,如果是回文,就加入在 path中,path用来记录切割过的回文子串。

代码如下:

class Solution {
    List<List<String>> result = new ArrayList<>();
    List<String> path = new ArrayList<>();

    public List<List<String>> partition(String s) {
        backtracking(s,0);
        return result;
    }

    private void backtracking(String s, int startIndex) {
        if (startIndex>=s.length()){
            result.add(new ArrayList(path));
        }

        for (int i = startIndex;i<s.length();i++){
            if (isPalindrome(s,startIndex,i)){
                String str = s.substring(startIndex, i + 1);
                path.add(str);
            }else {
                continue;
            }
            backtracking(s,i+1);
            path.remove(path.size()-1);
        }
        
    }
    private boolean isPalindrome(String s, int startIndex, int end) {
        for (int i = startIndex, j = end; i < j; i++, j--) {
            if (s.charAt(i) != s.charAt(j)) {
                return false;
            }
        }
        return true;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/197352.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

简易三子棋游戏实现

哈喽小伙伴们大家好&#xff0c;我们一起学习三子棋游戏的创建吧。在开始之前我们先来复习一下&#xff0c;函数声明放在头文件中函数定义放在源文件中。那么什么是函数声明和函数定义呢&#xff1f;所谓函数声明就是说明函数的返回参数&#xff0c;函数类型&#xff0c;函数名…

基于PHP的图书管理系统

摘要网络技术给生活带来了十分的便利。所以把图书管理与现在网络相结合。在图书馆发展的整个过程中&#xff0c;图书担负着最重要的角色。为满足如今日益复杂的管理需求&#xff0c;各类管理系统程序也在不断改进。本课题所设计的图书管理系统&#xff0c;使用B/S架构&#xff…

C++之this指针

this指针到底是什么&#xff1f;this 实际上是成员函数的一个形参&#xff0c;在调用成员函数时将对象的地址作为实参传递给 this。不过 this 这个形参是隐式的&#xff0c;它并不出现在代码中&#xff0c;而是在编译阶段由编译器默默地将它添加到参数列表中。我们操作一个对象…

Hadoop配置手册1:hadoop环境搭建与测试

Hadoop配置手册1 Date: September 25, 2022 第1章 hadoop环境搭建 1.1 安装Vmware软件 下载地址&#xff1a;https://www.onlinedown.net/soft/45831.htm 运行安装程序&#xff0c;并连续点击下一步安装 输入密钥&#xff0c;启动程序 详细参考&#xff1a;https://blog.csd…

2023年19个数学建模竞赛重磅来袭!!!

更新时间&#xff1a;2022年2月3日 本人的团队全是计算机的研究生&#xff0c;从本科到研究生有丰富的打比赛和数模的经验&#xff0c;有需要指导的&#xff0c;请私信我 相关链接 &#xff08;1&#xff09;【数学建模】2022年整年所有数学建模竞赛时间表 &#xff08;2&a…

再过半小时,你就能理解Kafka的基本原理了

kafka总结一.定义二.基础架构及术语三.工作流程分析3.1发送数据3.2保存数据3.2.1 partition结构3.2.2 message结构3.2.3 存储策略3.2.4 消费数据一.定义 Kafka是一种高吞吐量的分布式发布订阅消息系统&#xff0c;可以处理消费者规模的网站中的所有动作流数据&#xff0c;具有…

基于 PyTorch 的目标检测(YOLO实现)

目标检测是一个直到最近才开始逐渐被征服的挑战。解决这个问题对于自动化和自动驾驶来说是至关重要的。对解决办法的追求导致了各种方法的发展。我想要描述一些主要的方法&#xff0c;在过去的21目标检测已经被使用&#xff0c;然后讨论 Yolov3的实现。讨论方法引言虽然深度学习…

windows 7 离线安装vs20219,GraalVM 打包java成可执行程序

环境准备 由于vs2022不支持windows 7 &#xff0c;故用vs2019版。 如果是 win7 系统&#xff0c;在安装下载的依赖项前需要安装 win7 所需要的两个补丁 KB4490628和KB4474419 &#xff0c;下载地址分别为&#xff08;下载后直接安装即可&#xff09;&#xff1a; 参考这篇博客…

vite --- 搭建开发环境

目录 下载安装和初始化VSCode 安装Node.js yarn 使用 pnpm 安装与使用 搭建第一个Vite项目 使用 PNPM创建项目 项目目录解读 下载安装和初始化VSCode 1、访问网站 Visual Studio Code - Code Editing. Redefined 2、选择平台版本 选择符合自己操作系统的安装包下载完毕…

接口测试及接口抓包常用的测试工具有哪些?

目录 接口 接口测试的重要性 常用抓包工具 01、F12 02、Fiddler抓包工具 03、Charles抓包工具 04、Firebug抓包工具 05、httpwatch抓包工具 06、Wireshark抓包工具 07、SmartSniff抓包工具 常用接口测试工具 01、Postman 02、Jmeter 03、RESTClient 04、WireMock…

655. 汽车大甩卖2 etiger.vip 答案

题目描述 有n辆车大甩卖&#xff0c;第i辆车售价a[i]元。有m个人带着现金来申请购买&#xff0c;第i个到现场的人带的现金为b[i]元&#xff0c;只能买价格不超过其现金额的车子。你是大卖场总经理&#xff0c;希望将车和买家尽量多地进行一对一配对&#xff0c;请问最多卖出多…

Qt 开发环境搭建

一、Qt下载与安装 1、qt下载网站https://download.qt.io/ 其中各个目录含义如下&#xff1a; 目录说明snapshots/预览版&#xff0c;最新开发测试的Qt库和开发工具online/在线安装源official_releases/正式发布版&#xff0c;是与开发版相对应的稳定版Qt库和开发工具&#x…

利用哨兵简化实现难度

首先先回顾一下链表的插入和删除&#xff0c;如果需要在一个结点p后边插入一个结点&#xff0c;那么只需要下边两行代码&#xff1a; new_node->next p->next; p->next new_node;但是当往链表插入第一个结点时候&#xff0c;上边的代码就不能用了。需要进行下边的处…

【vue2】vue框架学习前置必备基础知识

&#x1f973;博 主&#xff1a;初映CY的前说(前端领域) &#x1f31e;个人信条&#xff1a;想要变成得到&#xff0c;中间还有做到&#xff01; &#x1f918;本文核心&#xff1a;数组 | 字符串中常用方法、对象解构语法、function |箭头函数this指向、展开运算符、原型…

为了会做题而学习期权合约

基本术语 买入期权&#xff1a;按照固定价格购买特定物品的期权。卖出期权&#xff1a;按照固定价格出售特定物品的期权。执行价格&#xff1a;期权合约中约定的固定价格。到期日&#xff1a;在其后期权不再被执行的日期。欧式期权&#xff1a;期权只能在到期日当日被执行。美…

python带你采集热点事件,让你第一时间掌握全发展

前言 嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 又到了学Python时刻~ 开发环境: python 3.8: 解释器 pycharm: 代码编辑器 requests: 发送请求 parsel: 解析数据 jieba pandas stylecloud 实现流程: 一. 思路分析 找到数据来源 network 记录网页数据 请求 二…

windows下djaongo项目移植至centos7系统并启动

概述&#xff1a;在windows下开发完成的django项目需要移植至centos系统并启动。 文章目录1,在django项目目录下生成requirements.txt文件2,下载FileZilla安装并连接Linux系统3,本地传输文件至linux系统3.1,可用vim修改settings.py的参数4,安装requirements.txt依赖包5,启动项目…

pwn小白入门 装载 笔记

所看视频奉上&#xff1a;5、装载与汇编_哔哩哔哩_bilibili笔记如下&#xff1a;1.查看文件类型&#xff1a;file 文件名其中&#xff1a;add&#xff1a;文件名ELF&#xff1a;文件格式64-bit&#xff1a;64位LSB&#xff1a;端序 lsb&#xff1a;小端序 msb:大端序x86-64:架构…

sqlserver2012数据库,日志文件损坏修复

背景 服务器突然断电&#xff0c;导致数据库日志文件损坏&#xff0c;数据库无法启动。 本方案也同样适用于不小心删除数据库日志文件的情况。 相关报错 master数据库日志异常&#xff0c;导致数据库无法启动&#xff1a; 无法在数据库“master”(数据库 ID 为 1)的分配单元 …

windows下生成自签证书并配置到chrome

Windows自签证书生成工具&#xff1a;XCA – X Certificate and Key Management 简称&#xff1a;XCA 下载地址&#xff1a; https://github.com/chris2511/xca/releases 或者 http://sourceforge.net/projects/xca/files/latest/download 界面&#xff08;1.4.1版本&#xff0…