算法训练day26 leetcode39组合总和 40组合总和Ⅱ 131分割回文串

2024-02-13 14:04

本文主要是介绍算法训练day26 leetcode39组合总和 40组合总和Ⅱ 131分割回文串,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

39 组合总和

题目描述

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

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

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

示例 1:

输入:candidates = [2,3,6,7], target = 7
输出:[[2,2,3],[7]]
解释:
2 和 3 可以形成一组候选,2 + 2 + 3 = 7 。注意 2 可以使用多次。
7 也是一个候选, 7 = 7 。
仅有这两种组合。

示例 2:

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

示例 3:

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

提示:

  • 1 <= candidates.length <= 30
  • 2 <= candidates[i] <= 40
  • candidates 的所有元素 互不相同
  • 1 <= target <= 40

题目分析

本题没有数量要求,可以无限重复,但是有总和的限制,所以间接的也是有个数的限制。

前端时间忙工作,落下了不少,分析后面就简略了

acm模式代码

#include <iostream>
#include <vector>class Solution{
private:std::vector<std::vector<int>> result;std::vector<int> path;void backtracking(std::vector<int>& candidates, int target, int sum, int startIndex) {if (sum > target) {return;}if (sum == target) {result.push_back(path);return;}for (int i = startIndex; i < candidates.size(); i++) {sum += candidates[i];path.push_back(candidates[i]);backtracking(candidates, target, sum, i); // 不用i + 1,表示可以重复读取当前数字sum -= candidates[i];path.pop_back();}}
public:std::vector<std::vector<int>> combinationSum(std::vector<int>& candidates, int target) {result.clear();path.clear();backtracking(candidates, target, 0, 0);return result;}};int main() {Solution sol;std::vector<int> candidates = {2, 3, 6, 7};int target = 7;std::vector<std::vector<int>> result = sol.combinationSum(candidates, target);std::cout << "Combinations summing to " << target << ":\n";for (const auto& combination : result) {std::cout << "[";for (size_t i = 0; i < combination.size(); ++i) {std::cout << combination[i];if (i < combination.size() - 1) std::cout << ", ";}std::cout << "]\n";}return 0;
}

40 组合总和

题目描述

给定一个候选人编号的集合 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

题目分析

本题的难点在于区别2中:集合(数组candidates)有重复元素,但还不能有重复的组合所以我们要去重的是同一树层上的“使用过”,同一树枝上的都是一个组合里的元素,不用去重

此题还需要加一个bool型数组used,用来记录同一树枝上的元素是否使用过。

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

acm模式代码

#include <iostream>
#include <vector>
#include <algorithm>class Solution{
private:std::vector<std::vector<int>> result;std::vector<int> path;void backtracking(std::vector<int>& candidates, int target, int sum, int startIndex, std::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);used[i] = false;sum -= candidates[i];path.pop_back();}}
public:std::vector<std::vector<int>> combinationSum2(std::vector<int>& candidates, int target) {std::vector<bool> used(candidates.size(), false);path.clear();result.clear();sort(candidates.begin(), candidates.end());backtracking(candidates, target, 0 ,0, used);return result;}
};int main() {Solution sol;std::vector<int> candidates = {10, 1, 2, 7, 6, 1, 5};int target = 8;std::vector<std::vector<int>> result = sol.combinationSum2(candidates, target);std::cout << "所有组合的数字之和等于 " << target << " 的唯一组合为:\n";for (const auto& combination : result) {std::cout << "[";for (size_t i = 0; i < combination.size(); ++i) {std::cout << combination[i];if (i < combination.size() - 1) std::cout << ", ";}std::cout << "]\n";}return 0;
}

131 分割回文串

题目描述

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

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

示例 1:

输入:s = "aab"
输出:[["a","a","b"],["aa","b"]]

示例 2:

输入:s = "a"
输出:[["a"]]

提示:

  • 1 <= s.length <= 16
  • s 仅由小写英文字母组成

题目分析

根据回溯算法模板

void backtracking(参数) {if (终止条件) {存放结果;return;}for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {处理节点;backtracking(路径,选择列表); // 递归回溯,撤销处理结果}
}

acm完整代码

#include <iostream>
#include <vector>
// #include <string>class Solution{
private:std::vector<std::vector<std::string>> result;std::vector<std::string> path;void backtracking(const std::string& s, int startIndex) {//如果起始位置已经大于s的大小了,说明已经找到一组分割方案了if(startIndex >= s.size()) {result.push_back(path);return;}for (int i = startIndex; i < s.size(); i++) {if (isPalindrome(s,startIndex, i)){//获取[startindex,i]在s中的子串std::string str = s.substr(startIndex, i - startIndex + 1);path.push_back(str);}else {continue;}backtracking(s, i+ 1);path.pop_back();}}bool isPalindrome(const std::string& s , int start, int end)  {for ( int i = start, j = end; i< j; i++ , j--) {if(s[i] != s[j]) {return false;}}return true;}
public:std::vector<std::vector<std::string>> partirion(std::string s) {result.clear();path.clear();backtracking(s, 0);return result;}
};int main() {Solution solution;std::string s = "aab";std::vector<std::vector<std::string>> partitions = solution.partirion(s);std::cout << "所有可能的回文分割方式:\n";for (const auto& partition : partitions) {for (const auto& str : partition) {std::cout << str << " ";}std::cout << "\n";}return 0;
}

这篇关于算法训练day26 leetcode39组合总和 40组合总和Ⅱ 131分割回文串的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/705726

相关文章

springboot+dubbo实现时间轮算法

《springboot+dubbo实现时间轮算法》时间轮是一种高效利用线程资源进行批量化调度的算法,本文主要介绍了springboot+dubbo实现时间轮算法,文中通过示例代码介绍的非常详细,对大家... 目录前言一、参数说明二、具体实现1、HashedwheelTimer2、createWheel3、n

SpringBoot实现MD5加盐算法的示例代码

《SpringBoot实现MD5加盐算法的示例代码》加盐算法是一种用于增强密码安全性的技术,本文主要介绍了SpringBoot实现MD5加盐算法的示例代码,文中通过示例代码介绍的非常详细,对大家的学习... 目录一、什么是加盐算法二、如何实现加盐算法2.1 加盐算法代码实现2.2 注册页面中进行密码加盐2.

Java时间轮调度算法的代码实现

《Java时间轮调度算法的代码实现》时间轮是一种高效的定时调度算法,主要用于管理延时任务或周期性任务,它通过一个环形数组(时间轮)和指针来实现,将大量定时任务分摊到固定的时间槽中,极大地降低了时间复杂... 目录1、简述2、时间轮的原理3. 时间轮的实现步骤3.1 定义时间槽3.2 定义时间轮3.3 使用时

C++字符串提取和分割的多种方法

《C++字符串提取和分割的多种方法》在C++编程中,字符串处理是一个常见的任务,尤其是在需要从字符串中提取特定数据时,本文将详细探讨如何使用C++标准库中的工具来提取和分割字符串,并分析不同方法的适用... 目录1. 字符串提取的基本方法1.1 使用 std::istringstream 和 >> 操作符示

如何通过Golang的container/list实现LRU缓存算法

《如何通过Golang的container/list实现LRU缓存算法》文章介绍了Go语言中container/list包实现的双向链表,并探讨了如何使用链表实现LRU缓存,LRU缓存通过维护一个双向... 目录力扣:146. LRU 缓存主要结构 List 和 Element常用方法1. 初始化链表2.

C++实现回文串判断的两种高效方法

《C++实现回文串判断的两种高效方法》文章介绍了两种判断回文串的方法:解法一通过创建新字符串来处理,解法二在原字符串上直接筛选判断,两种方法都使用了双指针法,文中通过代码示例讲解的非常详细,需要的朋友... 目录一、问题描述示例二、解法一:将字母数字连接到新的 string思路代码实现代码解释复杂度分析三、

golang字符串匹配算法解读

《golang字符串匹配算法解读》文章介绍了字符串匹配算法的原理,特别是Knuth-Morris-Pratt(KMP)算法,该算法通过构建模式串的前缀表来减少匹配时的不必要的字符比较,从而提高效率,在... 目录简介KMP实现代码总结简介字符串匹配算法主要用于在一个较长的文本串中查找一个较短的字符串(称为

通俗易懂的Java常见限流算法具体实现

《通俗易懂的Java常见限流算法具体实现》:本文主要介绍Java常见限流算法具体实现的相关资料,包括漏桶算法、令牌桶算法、Nginx限流和Redis+Lua限流的实现原理和具体步骤,并比较了它们的... 目录一、漏桶算法1.漏桶算法的思想和原理2.具体实现二、令牌桶算法1.令牌桶算法流程:2.具体实现2.1

使用Python实现批量分割PDF文件

《使用Python实现批量分割PDF文件》这篇文章主要为大家详细介绍了如何使用Python进行批量分割PDF文件功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、架构设计二、代码实现三、批量分割PDF文件四、总结本文将介绍如何使用python进js行批量分割PDF文件的方法

使用Python将长图片分割为若干张小图片

《使用Python将长图片分割为若干张小图片》这篇文章主要为大家详细介绍了如何使用Python将长图片分割为若干张小图片,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. python需求的任务2. Python代码的实现3. 代码修改的位置4. 运行结果1. Python需求