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
总结:该题和之前的组合有些差别,就是集合中的数是可以重复利用的。
①回溯的参数为,数组元素集合candidate,目标数字target,记录总和sum,记录遍历位置startindex。另外需要一个类内的数组记录当前的组合,一个类内的数组记录结果。无返回值。
②回溯的终止条件为,这道题没有个数的限制,只有总和的限制,所以总和sum便是该题的终止条件,当sum大于target的时候,直接返回,当sum等于target的时候,将当前的组合压入结果数组中,返回。
③回溯的单层逻辑为,从startindex开始遍历,到集合的大小为止。每次循环的循环体为将集合的值加入到sum中,并将该元素压入到path,调用回溯函数,此时的startindex仍然为i可以保证元素可以重复利用,最后将sum减去该元素值,并将path的顶部元素弹出完成回溯。返回。
解法代码:代码随想录 (programmercarl.com)
40.组合总和II
给定一个候选人编号的集合 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
总结:这道题比上一道题难在给的集合中元素可能是重复的,这将导致解集中出现重复;且要求集合元素中的元素只能使用一次。所以首先要保证集合是有序的,这样方便处理重复的元素。第二个要求(集合中的元素只能使用一次)可以通过每次调用回溯函数时给i+1作为startindex参数。第一个要求则复杂一点,需要定义一个bool类型数组记录该元素是否被用过,再加一个判断语句与前一个元素是否相等来进行判断要不要跳过该元素。
①回溯函数的参数为,给定的集合candidate,给定的目标值target,一个记录当前总和的sum,一个记录遍历位置的startindex指针,以及一个用于去重的bool类型数组used。类内还得定义一个记录结果的数组,一个记录当前组合的path。无返回值。
②回溯函数的终止条件和上一题一样,都是当sum等于目标值的时候将path压入result,大于目标值时返回。
③回溯函数的单层逻辑,首先判断,i>0&&candidate[i]==candidate[i-1]&&used[i-1]==false这个条件是否成立,成立则continue当前这一次循环。
然后将used[i]赋为true,将sum更新,将path更新。
调用回溯函数,将i+1作为参数放入。
回溯阶段将use[i]设置为false表示已经用过了,更新sum,更新path。
最后return。
解法代码:代码随想录 (programmercarl.com)
131.分割回文串
给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是 回文串 。返回 s 所有可能的分割方案。
回文串 是正着读和反着读都一样的字符串。
示例 1:
输入:s = "aab"
输出:[["a","a","b"],["aa","b"]]
示例 2:
输入:s = "a"
输出:[["a"]]
提示:
1 <= s.length <= 16
s 仅由小写英文字母组成
总结:该题算是比较难的题目,做题的思维跟不上,有些板块知道要做,却不知道怎么做。
①回溯函数的参数为,给定的字符串s,以及一个记录开始遍历位置的startindex。另外需要一个类内的数组作为结果,一个数组作为当前组合的记录path。无返回值类型。
②回溯函数的终止条件为,当startindex的值大于或者等于s.size的时候,说明找到切割字符串的方案了,这时将path装入结果数组中,return。
③回溯函数的单层逻辑为,首先是一个for循环,startindex为起始点,对字符串s进行遍历切割,for循环体为:先判断startindex起始点到i之间的字符串是否为回文,如果是则继续进行后面的代码;如果不是,则直接跳过当前这次循环。
如果是,则将startindex到i之间的字符串取出来放进path当中,取用s.substr()函数进行,放入两个参数,一个为起始节点参数,一个为取出的字符串大小。
接着调用回溯函数,将i+1作为startindex传入,代表从i+1开始进行新一轮切割方案的选择。
最后进行回溯,即将path中的顶部元素弹出。
返回。