首页 > 编程语言 >代码随想录算法训练营第二十七天|●39. 组合总和 ● 40.组合总和II ● 131.分割回文串(JS写法)

代码随想录算法训练营第二十七天|●39. 组合总和 ● 40.组合总和II ● 131.分割回文串(JS写法)

时间:2024-03-26 15:00:32浏览次数:19  
标签:return 组合 sum 随想录 start candidates path backTracking 总和

39 组合总和

题目链接/文章讲解:https://programmercarl.com/0039.%E7%BB%84%E5%90%88%E6%80%BB%E5%92%8C.html
视频讲解:https://www.bilibili.com/video/BV1KT4y1M7HJ
在这里插入图片描述
一开始自己写的大概和答案差不多,但是弄不明白回溯要传递的参数,但是自己一开始想到了终止条件,如果>7了就不对了,=7才对,<7就继续加
在这里插入图片描述

/**
 * @param {number[]} candidates
 * @param {number} target
 * @return {number[][]}
 */
var combinationSum = function(candidates, target) {
    let res = [];
    let path = [];
    const backTracking = (start,sum) => {
        // let sum = 0;
        //终止条件
        if(sum >= target){
            if(sum === target){
                res.push(path.slice());            
            }
            return;
        }
        
        //单层循环
        for(let i = start;i<candidates.length;i++){
            path.push(candidates[i]);
            //如果把sum的计算写在外面,由于回溯,在下面也要撤销
            //也可以直接写成backTracking(i,sum+candidates[i]);
            sum += candidates[i];   
            // 基于此继续选择,传i,下一次就不会选到i左边的数(但会选到i,也就是会选到自己)
            //传i+1就不会选到自己了
            //从自己本身开始,不选到左边的数据,也是一种剪枝
            backTracking(i,sum);
            sum -= candidates[i]; 
            path.pop();
        }
    }
    backTracking(0,0);
    return res;

};

40 组合总和Ⅱ

题目链接/文章讲解:https://programmercarl.com/0040.%E7%BB%84%E5%90%88%E6%80%BB%E5%92%8CII.html
视频讲解:https://www.bilibili.com/video/BV12V4y1V73A
在这里插入图片描述
本题一开始给的candidates可能会包含重复的元素,这一点我一开始忽视了,导致我以为和39题基本一致,只需要在for循环的的回溯用i+1即可,但是给出的答案是包含重复组合的。
这道题目和39.组合总和 (opens new window)如下区别:

本题candidates 中的每个数字在每个组合中只能使用一次。
本题数组candidates的元素是有重复的,而39.组合总和 (opens new window)是无重复元素的数组candidates
最后本题和39.组合总和 (opens new window)要求一样,解集不能包含重复的组合。

本题的难点在于区别2中:集合(数组candidates)有重复元素,但还不能有重复的组合。
这个去重为什么很难理解呢,所谓去重,其实就是使用过的元素不能重复选取。 这么一说好像很简单!

都知道组合问题可以抽象为树形结构,那么“使用过”在这个树形结构上是有两个维度的,一个维度是同一树枝上使用过,一个维度是同一树层上使用过。没有理解这两个层面上的“使用过” 是造成大家没有彻底理解去重的根本原因。

那么问题来了,我们是要同一树层上使用过,还是同一树枝上使用过呢?

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

所以我们要去重的是同一树层上的“使用过”,同一树枝上的都是一个组合里的元素,不用去重。
强调一下,树层去重的话,需要对数组排序!
在这里插入图片描述
在这里插入图片描述
本题相较于39只需要改动以下三点:
在这里插入图片描述

/**
 * @param {number[]} candidates
 * @param {number} target
 * @return {number[][]}
 */
var combinationSum2 = function(candidates, target) {
    let res = [];
    let path = [];
    candidates.sort((a,b) => a-b);
    const backTracking = (start,sum) => {
        //终止条件
        if(sum >= target){
            if(sum === target){
                res.push(path.slice());
                return;
            }
            return;
        }        
        //单词循环逻辑
        for(let i = start;i<candidates.length;i++){
            if (i - 1 >= start && candidates[i - 1] == candidates[i]) { // 当前选项和左邻选项一样,跳过
                continue;
            }
            path.push(candidates[i]);
            backTracking(i+1,sum+candidates[i]);
            path.pop();
        }
    }
    backTracking(0,0);
    return res;


};

131 分割回文串

https://programmercarl.com/0131.%E5%88%86%E5%89%B2%E5%9B%9E%E6%96%87%E4%B8%B2.html
视频讲解:https://www.bilibili.com/video/BV1c54y1e7k6
在这里插入图片描述
在这里插入图片描述

/**
 * @param {string} s
 * @return {string[][]}
 */
 //判断是不是回文字符串
 const isPalindrome = (s,l,r) => {
    for(let i = l,j = r;i<j;i++,j--){
        if(s[i] !== s[j]) return false;
    }
    return true;
 }
var partition = function(s) {
    const res = [];
    const path = [];
    function backTracking(start){
        //终止条件,start代表切割符号,start走到最后了,那也就结束了
        if(start >= s.length){
            // res.push(Array.from(path));
            res.push(path.slice());
            return;
        }
        for(let i = start;i<s.length;i++){
            //需要判断的是[start,i]这个区间内截取的子串
            //如果不是回文子串则跳过本次循环
            if(!isPalindrome(s,start,i)) continue;
            path.push(s.slice(start,i+1));
            //寻找i+1为起始位置的子串
            //注意切割过的位置,不能重复切割,所以,backtracking(s, i + 1); 传入下一层的起始位置为i + 1
            backTracking(i+1);
            path.pop();
        }
    }
    backTracking(0);
    return res;
};

标签:return,组合,sum,随想录,start,candidates,path,backTracking,总和
From: https://blog.csdn.net/weixin_44776979/article/details/136854651

相关文章

  • 代码随想录第20天| 654.最大二叉树 617.合并二叉树
     654.最大二叉树654.最大二叉树-力扣(LeetCode)代码随想录(programmercarl.com)又是构造二叉树,又有很多坑!|LeetCode:654.最大二叉树_哔哩哔哩_bilibili给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建:创建一个根节点,其值为 ......
  • 代码随想录第18天 | 513.找左下角的值 112.路径总和
    513.找左下角的值513.找树左下角的值-力扣(LeetCode)代码随想录(programmercarl.com)怎么找二叉树的左下角?递归中又带回溯了,怎么办?|LeetCode:513.找二叉树左下角的值_哔哩哔哩_bilibili给定一个二叉树的 根节点 root,请找出该二叉树的 最底层 最左边 节点的值。假......
  • 代码随想录第六天: 哈希表(数组+HashSet+HashMap)
    语言:Java参考资料:代码随想录、ChatGPT3.5当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法。但是哈希法也是牺牲了空间换取了时间,因为我们要使用额外的数组,set或者是map来存放数据,才能实现快速的查找。如果在做面试题目的时候遇到需要判断一个......
  • 代码随想录第四天 链表Part02
    语言:Java参考资料:代码随想录、ChatGPT3.524.两两交换链表中的节点力扣题目链接(opensnewwindow)给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。思路这道题目正常模拟就可以了。建议......
  • 代码随想录第一天-双指针+二分法
    参考资源:https://programmercarl.com/、ChatGPT3.5语言:Java二分法二分法,又称为二分查找或折半查找,是一种在有序数组中查找目标值的算法。它的基本思想是将目标值与数组中间的元素进行比较,若目标值等于中间元素,则查找成功;若目标值小于中间元素,则在数组的左半部分继续查......
  • 代码随想录 Day3 数组 | LC977 有序数组的平方 & LC209 长度最小的子数组(滑动窗口))
    四、有序数组的平方题目:力扣977:有序数组的平方给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。示例1:输入:nums=[-4,-1,0,3,10]输出:[0,1,9,16,100]解释:平方后,数组变为[16,1,0,9,100]排序后,数组变为[......
  • 2的n次种组合
    #include<stdio.h>#include<limits.h>//用于INT_MAX intminCost(intn,intx,intprices[]){  intminCost=INT_MAX;//初始化最小花费为最大整数值  inttotalCost,i,j;  intstate,bitMask;//state用于遍历所有组合,bitMask用于检查某一位......
  • 代码随想录刷题记录4——滑动窗口和螺旋矩阵
    数组:701.二分查找27.移除元素977.有序数组的平方209.长度最小的子数组59.螺旋矩阵思路:209.长度最小的子数组只要知道要用滑动窗口的思路来写就好了!滑动窗口本质上就是双指针核心问题是考虑好窗口什么时候变大什么时候变小59.螺旋矩阵并没有什么新的算法思想,但......
  • 06天【代码随想录算法训练营34期】 第三章 哈希表part01(● 242.有效的字母异位词 ●
    242.有效的字母异位词思路:26位的array,每个分别对应a,b,c...,z,如果遇到一个字母就++,如果两个array一样则为anagramhint:toinitiateanarraywithnelementscarryingvalue0:arr=[]arr=[0foriinrange(n)]print(arr)classSolution:defisAnagram(self,......
  • 代码随想录算法训练营第五十七/天 | 516. 最长回文子序列,647. 回文子串
     动态规划最强总结篇!如今动态规划已经讲解了42道经典题目,共50篇文章,是时候做一篇总结了。关于动态规划,在专题第一篇关于动态规划,你该了解这些! (opensnewwindow)就说了动规五部曲,而且强调了五部对解动规题目至关重要!这是Carl做过一百多道动规题目总结出来的经验结晶啊......