@[TOC](Leetcode 77. Combinations (python+cpp))
题目
解法1
这道题目和46可以放在一起看。46是排列,而这题是组合,区别就在于组合不考虑位置,而排列会考虑位置。对比一下唯一的区别在于,当进行递归的时候,排列传进去的是当前所在level+1的位置,而组合传进去的应该是当前遍历的i+1,结合两题的代码就很好懂了。举个例子,传i+1的话,n = 4, k = 2时,答案应该是[[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]],而如果你传level+1话,答案就变成这样了
[[1,2],[1,3],[1,4],[2,2],[2,3],[2,4],[3,2],[3,3],[3,4],[4,2],[4,3],[4,4]]。
python代码如下:
class Solution:
def combine(self, n: int, k: int) -> List[List[int]]:
def back_tracking(first=1,comb=[]):
if len(comb)==k:
ans.append(comb[:])
return
for i in range(first,n+1):
comb.append(i)
back_tracking(i+1,comb)
comb.pop()
ans = []
back_tracking()
return ans
C++版本如下:
class Solution {
public:
vector<vector<int>> combine(int n, int k) {
vector<vector<int>> ans;
vector<int> comb;
back_tracking(ans,comb,1,k,n);
return ans;
}
void back_tracking(vector<vector<int>>& ans, vector<int>& comb, int first,int k,int n){
if (comb.size()==k){
ans.push_back(comb);
return;
}
for(int i=first;i<=n;++i){
comb.push_back(i);
back_tracking(ans,comb,i+1,k,n);
comb.pop_back();
}
}
};
解法2:
根据(这边排列的题目的标准解法3)[https://blog.csdn.net/qq_37821701/article/details/105747381]来进行改动达到组合的效果
只需要做一个改动,就是保证list里面的数字都是生序的,这样就可以保证不会出现数字重复的组合
class Solution:
def combine(self, n: int, k: int) -> List[List[int]]:
def backtracking(i):
if i == k:
ans.append(c[:])
return
for j in range(1,n+1):
if j in visited or (i>0 and j <= c[i-1]):
continue
c[i] = j
visited[j] = True
backtracking(i+1)
c[i] = 0
visited.pop(j)
c = [0] * k
ans = []
visited = {}
backtracking(0)
return ans