今天是2021.4.2日,笔试携程的一道题的时候出现大问题,明明思路是对的,就是过不了,于是不开心了一天,一直在思考是哪里的问题,现在忽然发现哦,茅塞顿开,按照这个思路来做,再有回溯的题不会我是猪。
回溯主要用来在一颗解空间树上求哪种拥有想要的效果。
其实就是解决子序列问题的,子序列问题的暴力解就是回溯。
在一排列组合的大树中,要哪个元素不要哪个元素,其实总结起来就很简单,三种情况。
一定要画出解空间树的图来,才能确定怎么来回溯。
排列
第一种是排列,也就是所有的元素都得要,只不过排的顺序不同,它用的方法是used数组来去掉在一次递归中的重复元素选择,递归进去的时候就把这个元素的used数组设为true。
因为所有的元素都有,所以结束条件为深度等于数组长度。
如果有重复元素,则先排序,然后在for循环选择时跳过和上一个一样的,怎么区分是不是在范围选择,就是看上一个的used数组有没有恢复原样。
组合
组合是在数组中随便选数字,只要满足条件即可,它在选择过后后面的元素也不能出现,用的是begin来操控。如果此时元素在递归中可重复,则在递归中传入的begin就是i。如果不重复,传入的begin就是i+1。
这样的话就没法用深度来控制结束条件了,需要用的是要达成的目标。
如果有重复元素需要跳过的话,就需要先排序,然后看需不需要跳过。怎么判断此时是条件选择而不在递归,就想此时的i已经超过了,只要i>begin,说明已经跳出递归。
子集
子集是组合的一种,所有元素都要,也就是说没有结束条件,每个都添加就完了。
所以碰到一个子序列的题,先想用动态规划,如果想不出来,则用回溯,一定要注意是组合还是排列,以此来决定它的结束条件。