代码随想录第二十四天|回溯第一天:懵逼
Leetcode 77. 组合
题目链接: 组合
自己的思路:第一天开回溯,感觉和递归很像,因为我都不会!多做多练!!!
正确思路:回溯就是for循环里面套递归,这个题很好理解,但是不好写代码,我们假设n=4,k=2来处理,第一次从n里面挑一个1,然后再把234拿出来,只拿比1大的,然后再从234里面拿,分别拿2、3、4,这样就构成了[1,2]、[1,3]、[1,4],其他的也是同理,说明终止条件就是数组大小满足k的时候就加入进来,for循环里面从1到n,每次的起始点也不同;但是这道题我们还可以做剪枝操作,因为后面有些数组的长度是永远都没法到k的,我们假设现在路径中有了path.size()个元素,那k-path.size()就是我们还需要多少元素,那n-(k-path.size())+1就是我们最大能开始的起始点,这里加1是为了刨去当前元素,从当前元素的后一个元素开始,因为后面的起始点所产生的数组的长度不会等于k,所以剪枝!!!
回溯三部曲:1、终止条件:当path的数组大小满足k的时候,将路径加入到结果当中,然后返回;2、传入参数:n、k和当前元素的起始值;3、单层逻辑:for循环用于指定不同的初始值,先把当前初始值加入进来,然后使用递归函数进行递归,然后再把当前值去除掉(回溯)!!!
代码:
class Solution {
List<List<Integer>> res = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
public List<List<Integer>> combine(int n, int k) {
backtracking(n,k,1);
return res;
}
public void backtracking(int n,int k,int startindex){
if (path.size()==k){
//满足条件则加入进来
res.add(new ArrayList(path));
return;
}
//剪枝操作
//把后面不满足数组长度的都剪掉
for (int i = startindex;i<=n-(k-path.size())+1;i++){
path.add(i);
backtracking(n,k,i+1);
path.removeLast();
}
}
}
复杂度分析:
时间复杂度:
O
(
n
)
\mathcal{O}(n)
O(n)
空间复杂度:
O
(
1
)
\mathcal{O}(1)
O(1)