77. Combinations 组合
作者: 负雪明烛 id: fuxuemingzhu 个人博客: https://fuxuemingzhu.cn/
题目地址:https://leetcode.com/problems/combinations/description/
Given two integers n and k, return all possible combinations of k numbers out of 1 … n.
For example,If n = 4 and k = 2, a solution is:
[ [2,4], [3,4], [2,3], [1,2], [1,3], [1,4],]找出一个数组的所有可能的组合。
方法一:递归
Section titled “方法一:递归”这个题要找到组合,组合和排列的不同之处在于组合的数字出现是没有顺序意义的。
剑指offer的做法是找出n个数字中m的数字的组合方法是,把n个数字分成两部分:第一个字符和其他的字符。如果组合中包括第一个字符,那么就在其余字符中找到m-1个组合;如果组合中不包括第一个字符,那么就在其余字符中找到m个字符。所以变成了递归的子问题。
我的做法如下,这个之中用到了if k > len(array)的做法,防止数组过界陷入死循环(其作用主要是对第二个递归而言的)。
class Solution(object): def combine(self, n, k): """ :type n: int :type k: int :rtype: List[List[int]] """ res = [] self.helper(range(1, n + 1), k, res, []) return res
def helper(self, array, k, res, path): if k > len(array): return if k == 0: res.append(path) else: self.helper(array[1:], k - 1, res, path + [array[0]]) self.helper(array[1:], k, res, path)方法二:回溯法
Section titled “方法二:回溯法”这样的思想是我们抽取第一个字符,然后从后面n-1个字符中抽出m-1个;抽取第二个字符,再从后面的n-2个字符抽出m-1个……这样循环下去。因为这样的操作每次都是往后进行寻找的,所以不用考虑去重的问题。
class Solution(object): def combine(self, n, k): """ :type n: int :type k: int :rtype: List[List[int]] """ res = [] self.helper(range(1, n + 1), k, res, []) return res
def helper(self, array, k, res, path): if k > len(array): return if k == 0: res.append(path) else: for i in range(len(array)): self.helper(array[i + 1:], k - 1, res, path + [array[i]])C++代码如下:
class Solution {public: vector<vector<int>> combine(int n, int k) { vector<int> nums(n, 0); for (int i = 1; i <= n; i++) { nums[i - 1] = i; } vector<vector<int>> res; helper(nums, res, {}, 0, k); return res; } void helper(const vector<int>& nums, vector<vector<int>>& res, vector<int> path, int start, int remain) { if (start > nums.size()) return; if (remain == 0) { res.push_back(path); return; } for (int i = start; i < nums.size(); i++) { path.push_back(nums[i]); helper(nums, res, path, i + 1, remain - 1); path.pop_back(); } }};2018 年 3 月 11 日 2018 年 12 月 20 日 —— 感冒害的我睡不着

评论与交流