LeetCode 77 组合 题解
LeetCode链接
给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。
你可以按 任何顺序 返回答案。
示例 1:
输入:n = 4, k = 2
输出:
[
[2,4],
[3,4],
[2,3],
[1,2],
[1,3],
[1,4],
]
示例 2:
输入:n = 1, k = 1
输出:[[1]]
提示:
1 <= n <= 20
1 <= k <= n
方法:
1. 找规律:见文档:
http://note.youdao.com/noteshare?id=18d45d64e392475065dc1fd946261192&sub=658D4B923ED941C299B8B4956DCBCEE5
个人感觉时间复杂度是O(k(n-k))=O(nk)
,因为递归深度最大是O(k)
,for循环量级是n-k
空间复杂度是O(k)+O(k)=O(k)
,tmp的额外空间和递归深度
2.组合型枚举,见官方题解
/**
* @author LiMin
* @Title: ComBine
* @Description:
* @date 2020/9/9 9:48
*/
import java.util.ArrayList;
import java.util.List;
/**
* @ClassName ComBine
* @Discription 从1~n的自然数中找出
* @Author lemon
* @Date 2020/4/2 14:59
**/
public class ComBine {
public static void main(String[] args) {
ComBine comBine = new ComBine();
comBine.comBine1(4, 2);
}
public List<List<Integer>> comBine1(int n, int k) {
List<Integer> tmp = new ArrayList<>();
List<List<Integer>> result = new ArrayList<>();
dfs1(result, tmp, k, n);
return result;
}
//代表从k~n里取k个数的组合,先取大的
public void dfs1(List<List<Integer>> result, List<Integer> tmp, int k, int n) {
if (k <= 0 || k > n) return;
for (int i = n; i >= k; --i) {
tmp.add(i);
if (k > 1) {
dfs1(result, tmp, k - 1, i - 1);//这里注意一下,下一个数一定是从i-1开始的而不是n-1开始
} else {
result.add(new ArrayList(tmp));
}
tmp.remove(tmp.size() - 1);
}
}
public List<List<Integer>> comBine2(int n, int k) {
List<Integer> tmp = new ArrayList<>();
List<List<Integer>> result = new ArrayList<>();
dfs2(result, tmp, k, n, 1);
return result;
}
public void dfs2(List<List<Integer>> result, List<Integer> tmp, int k, int n, int cur) {
if (k <= 0 || k > n) return;
if ((tmp.size() + n - cur + 1) < k) {
return;
}
if (tmp.size() == k) {
result.add(new ArrayList<>(tmp));
return;
}
//选中当前值
tmp.add(cur);
dfs2(result, tmp, k, n, cur + 1);
//不选当前值
tmp.remove(tmp.size() - 1);//这里可以理解一下,上面那个递归会一直深入到最后一个数放进去
dfs2(result, tmp, k, n, cur + 1);
}
}
又写了一个字典序排列
的,自己都觉得奇奇怪怪
public void dfs(List<List<Integer>> result, List<Integer> tmp, int k, int n,int cur){
if(k<=0||k>n) return;
//注意边界条件,cur代表当前位数值从cur开始;n-k+tmp.size()+1代表当前位能达到的最大数字
for(int i=cur;i<=n-k+tmp.size()+1;++i){
tmp.add(i);
if(tmp.size()<k){
dfs(result,tmp,k,n,i+1);//当前位是i,那么下一位至少要比i大1
}
else{
result.add(new ArrayList(tmp));
}
tmp.remove(tmp.size()-1);
}
}