代码随想录算法训练营第27天 | 39.组合总和 、40.组合总和II和131.分割回文串
链接: 39.组合总和
链接: 40.组合总和II
链接: 131.分割回文串
自己看到题目的第一想法
39.组合总和:数字可以被无限选取,那么startIndex就不是像之前组合问题一样了。不管怎样先画树形图自己模拟一下流程,画树形图的时候明确了两个点:第一就是每个节点处剩下的集合是什么?第二个是树的宽度和深度由什么决定?根据回溯的算法模板和三部曲一步步写代码。
40.组合总和II: 我看示例的时候有个疑问:题目要求candidates中的每个数字在每个组合中只能使用一次,那么candidates本身有重复的数字是算一个数字还是多个数字呢?如果是多个数字,为什么在结果里不能各自区分不同?
看完代码随想录之后的想法
39.组合总和:递归函数参数:集合candidates,目标值target,path的和sum,for循环的起始位置startIndex。**什么时候用startIndex?**当每一层选取都在同一个集合时需要startIndex,因为当前path新增的元素会影响集合元素的选取,也就是for循环里变量i的起始是由递归函数上一个i决定的。这里的具体对应关系也体现在递归处理逻辑中递归函数的输入参数中对应startIndex处的变量。由于这道题目可以重复选择元素,所以函数处理逻辑里startIndex取i,而上一题不能重复选取的startIndex为i+1。
40.组合总和II:针对去重的逻辑,有一个很需要理解的点,在于树枝去重还是树层去重。树枝去重保证了单个结果中元素值不会重复,而树层去重保证了结果集合中结果不会重复。针对这道题目,单个结果中元素值可以重复而结果集合中结果不能重复,所以应该使用树层去重。树枝去重用break(直接结束循环),树层去重用continue(跳过语句进入下一次循环)。看到这里其实也解答了我的疑问,题目要求的是组合,我思考的虽然元素不同,但是对于结果集合来说,它们之间不能有重复的。怎样进行树层去重呢? 首先需要进行排序,保证相同的数位置相邻。使用标记数组来记录被选取的元素,如果当前搜索到的节点已经被访问过,也就是数值与上一个相同且上一个没有被用过,那么就直接跳过此次循环进入下一个循环。
131.分割回文串:切割问题与组合问题相似,切割线就是startIndex,注意是startIndex而不是i,i是变化的,而startIndex是不变的。结束条件就是startIndex比字符串大或者已经等于字符串长度了。如何记录切割子串呢?先判断是否是回文,需要再写一个函数判断回文,也就是从前往后开始到从后往前,字符串相同。如果是回文子串就加入path中。
自己实现过程中遇到哪些困难
39.组合总和:一些薄弱点是,第一,对于数组的增删改查API太久没有写代码忘记了。第二,对于递归函数的参数还不是很熟练,第三是对于startIndex控制剩余集合的操作不是很熟练,与上一题对比下,这一题的递归函数的startIndex不太一样。
最后一题确实难,需要反复去回顾。