首页 > 编程语言 >算法随想Day24【回溯算法】| LC39-组合总和、LC40-组合总和Ⅱ、LC131-分割回文串

算法随想Day24【回溯算法】| LC39-组合总和、LC40-组合总和Ⅱ、LC131-分割回文串

时间:2023-02-27 20:44:06浏览次数:40  
标签:组合 temp int 算法 vector candidates result target 总和

LC39. 组合总和

vector<int> temp;
int sum = 0;
void combinationSumLoop(vector<vector<int>>& result, vector<int>& candidates, int index, const int& target)
{
    if (sum > target)
    {
        return;
    }
    if (sum == target)
    {
        result.emplace_back(temp);
        return;
    }
    for (int i = index; i < candidates.size(); i++)
    {
        temp.emplace_back(candidates[i]);
        sum += candidates[i];
        combinationSumLoop(result, candidates, i, target);
        temp.pop_back();
        sum -= candidates[i];
    }
}
vector<vector<int>> combinationSum(vector<int>& candidates, int target)
{
    vector<vector<int>> result;
    combinationSumLoop(result, candidates, 0, target);
    return result;
}

LC40. 组合总和Ⅱ

注释中,开始时这样的判断是不合理的,改进的是,要考虑到两种情况:

  • 如例子1, 1, 2, 2, 2, 5 ,target = 5,不去重的话,会出现很多[1, 2, 2]的重复组合
  • 有可能是第一个“1”递归完了,往右访问到第二个“1”的时候,重复了
  • 也可能是在第一个“1”递归中,把前两个“2”放入temp后,往右访问到下一个“2”时,重复了

所以为了同时顾及上述两种情况,用一个变量prev_pop去保存上一次回溯时pop出来的值,下次往前访问时,对比是否与该值一致,是则跳过这次递归。

vector<int> temp;
int sum = 0;
int prev_pop = 0;
void combinationLoop(vector<vector<int>>& result, vector<int>& candidates, int index, const int& target)
{
    if (sum > target)
    {
        return;
    }
    if (sum == target)
    {
        result.emplace_back(temp);
        return;
    }
    for (int i = index; i < candidates.size(); i++)
    {
        // if ((i != 0 && candidates[i] == candidates[i - 1] && temp.size() == 0) ||
        //     (temp.size() != 0 && candidates[i] == temp.back()))
        // {
        //     continue;
        // }
        if (candidates[i] == prev_pop)
        {
            continue;
        }
        temp.emplace_back(candidates[i]);
        sum += candidates[i];
        combinationLoop(result, candidates, i + 1, target);
        prev_pop = temp.back();
        temp.pop_back();
        sum -= candidates[i];
    }
}
vector<vector<int>> combinationSum2(vector<int>& candidates, int target)
{
    vector<vector<int>> result;
    sort(candidates.begin(), candidates.end());
    combinationLoop(result, candidates, 0, target);
    return result;
}

LC131. 分割回文串

开始没想到分割字符串的思想,看了讲解,自己写一遍代码。

本题要注意的细节比较多,在终止条件的确定上卡顿了一些时间:

  • 开始partitionLoop函数中的string& s,是使用string s的,每层递归有自己的s空间,但后面发现这样会很难做递归的整体管理,而且不好设定判断终止条件,开始定义了一个index参数,比较index == 源s.size()时return,但这道题不能保证每个字符串的递归深度,所以还是采用了string& s统一对源s字符串进行存储,同时对递归函数传s的索引下标(left、right)进行管理。
  • 终止条件,当left == right时,已经作废了,这时也不会进入for循环了
  • 开始对if (isPalindrome(str) == true)的判断,没有做else处理。没有考虑的情况,如例子,源s = "abaa",若没有else处理,第一个a放入了temp中,判断"ba"不是回文串,但由于没做退出处理,在下一轮递归中,判断最后一个"a"是回文串,从而导致这次的temp结果记录的是["a", "a"],出现了非预期结果。
vector<string> temp;
bool isPalindrome(string str)
{
    bool flag = true;
    int left = 0;
    int right = str.size() - 1;
    while (left < right)
    {
        if (str[left++] != str[right--])
        {
            flag = false;
        }
    }
    return flag;
}
void partitionLoop(vector<vector<string>>& result, string& s, int left, int right)
{
    if (left >= right)
    {
        result.emplace_back(temp);
        return;
    }
    for (int i = left; i < right; i++)
    {
        string str(s.begin() + left, s.begin() + i + 1);
        if (isPalindrome(str) == true)
        {
            temp.emplace_back(str);
        }
        else
        {
            continue;
        }
        partitionLoop(result, s, i + 1, right);
        temp.pop_back();
    }
}
vector<vector<string>> partition(string s)
{
    int size = s.size();
    vector<vector<string>> result;
    partitionLoop(result, s, 0, size);
    return result;
}

标签:组合,temp,int,算法,vector,candidates,result,target,总和
From: https://www.cnblogs.com/Mingzijiang/p/17161822.html

相关文章

  • 合并区间算法示意
    给定一堆区间,可能存在交集,对区间进行合并返回没有交集的区间集合。本文记录了这种问题的一种解法importjava.util.ArrayList;importjava.util.Arrays;importjava.uti......
  • 代码随想录算法训练营Day27 回溯算法|39. 组合总和 40.组合总和II 131.分割回文串
    代码随想录算法训练营39.组合总和题目链接:39.组合总和给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 targ......
  • LSB隐写分析算法实现
    分析步骤确定LSB嵌入的方式:LSB嵌入方式有很多种,如连续LSB嵌入、随机LSB嵌入、二进制交替LSB嵌入等。不同的嵌入方式对应着不同的检测方法,因此,在开始编写算法之前,需要确定......
  • LeetCode 周赛 334,在算法的世界里反复横跳
    本文已收录到AndroidFamily,技术和职场问题,请关注公众号[彭旭锐]提问。大家好,我是小彭。今天是LeetCode第334场周赛,你参加了吗?这场周赛考察范围比较基础,整体难度......
  • python算法基础
    一、简介定义和特征定义:算法(Algorithm)是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制。也就是说,能够对一定......
  • JAVA加载PMML算法模型
    注:加载失败时尝试修改pmml文件版本为4.3依赖<dependency><groupId>org.jpmml</groupId><artifactId>pmml-evaluator</artifactId><version>1.4.1</versi......
  • topN算法问题
    问题:如何在10亿个整数中找出前1000个最大的数?小顶堆堆排序首先,我们需要构建一个大小为N(1000)的小顶堆,小顶堆的性质如下:每一个父节点的值都小于左右孩子节点,然后依次从......
  • 【算法笔记】Day of Week
    DayofWeek时间限制:1Sec  内存限制:32MB提交:2252  解决:692 题目描述WenowusetheGregorianstyleofdatinginRussia.Theleapyearsareyearswith......
  • stl算法汇总
          ......
  • 数的进制转换【《算法竞赛进阶指南》】
    数的进制转换编写一个程序,可以实现将一个数字由一个进制转换为另一个进制。这里有62个不同数位{0−9,A−Z,a−z}。输入格式第一行输入一个整数,代表接下来的行数。......