77.Combinations - medium
给定两个整数 n, k ,求 1 ~ n 中任取 k 个数的组合方式。
Input: n = 4, k = 2
Output:
[
[2,4],
[3,4],
[2,3],
[1,2],
[1,3],
[1,4],
]
思路:
一开始准备用迭代去做,感觉不好做,还是只能用递归的DFS来做,设一个临时容器 tmp ,以及一个记录起点的变量 start ,每一次从 start 开始循环,递归往里面放一个数,当容器 tmp 里面的个数等于 k 个时,就将这个容器写入到最终的结果容器中,然后返回上一层,再将这一层中放入的数字 pop_back( ),再重新放入下一个数字,不断的循环递归。
class Solution { public: vector<vector<int>> combine(int n, int k) { vector<vector<int>> res; vector<int> tmp; combineDFS(tmp, n, k, 1, res); return res; } void combineDFS(vector<int>& tmp, int n, int k, int start, vector<vector<int>>& res) { if (tmp.size() == k) { res.push_back(tmp); return; } for (int i = start; i <= n; i++) { tmp.push_back(i); combineDFS(tmp, n, k, i + 1, res); tmp.pop_back(); } } };
注意的点:
对于容器tmp,用引用快很多,因为系统不用每一次递归都开辟空间、回收空间,时间复杂度和空间复杂度都大幅度缩小:
void combineDFS(vector<int>& tmp, int n, int k, int start, vector<vector<int>>& res)
和
void combineDFS(vector<int> tmp, int n, int k, int start, vector<vector<int>>& res)
引用比非引用快10倍还多。
Java 版:
• 深度优先搜索 DFS,设一个临时容器 tmp ,以及一个记录起点的变量 start ,每一次从 start 开始循环,往里面放一个数;
• 当容器 tmp 里面的元素个数等于 k 时,将容器中的元素加入到结果集;
• 返回上一层,再将这一层中放入的数字弹出,重新放入下一个数字,不断的循环递归。
class Solution { public List<List<Integer>> combine(int n, int k) { List<List<Integer>> res = new ArrayList<>(); DFS(new ArrayList<>(), 1, n, k, res); return res; } public void DFS(List<Integer> tmp, int start, int n, int k, List<List<Integer>> res){ if(tmp.size() == k){ res.add(new ArrayList(tmp)); //满足条件,则加入结果集 return; } for(int i = start; i <= n; i++){ tmp.add(i); //加入 DFS(tmp, i + 1, n, k, res); //这儿是 i+1 , 不是 start + 1,和 46题区分 if(tmp.size() > 0) tmp.remove(tmp.size()-1);//弹出最新加入的 } } }