LeetCode:Combinations
题目链接
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], ]
分析:
求所有的组合
算法1:递归解法,仿照根据LeetCode:Subsets 的算法1解法,每一个元素有两种状态:选择、不选择
1 class Solution { 2 public: 3 vector<vector<int> > combine(int n, int k) { 4 vector<vector<int> >res; 5 vector<int>tmpres; 6 helper(1,n,k,tmpres,res); 7 return res; 8 } 9 10 //从[left, right]范围内选取k个数,tmpres是一个临时组合 11 void helper(int left, int right, int k, vector<int> &tmpres, vector<vector<int> >&res) 12 { 13 if(right-left+1 < k)return; 14 if(k == 0) 15 { 16 res.push_back(tmpres); 17 return; 18 } 19 //选择left 20 tmpres.push_back(left); 21 helper(left+1, right, k-1, tmpres, res); 22 tmpres.pop_back(); 23 //不选择left 24 helper(left+1, right, k, tmpres, res); 25 } 26 };
算法2:还有另一种递归的思路,以一个例子来解释这种方法,假如要在6个元素(1,2,3,4,5,6)中选取3个元素,(我们对选取的元素组合加一个限制:选取的3个元素的相对顺序和他们在原始数组中的顺序一致,对于组合问题,这个条件对结果没有影响):
- 选取第一个元素:第一个元素只能从[1,2,3,4]中选取,因为如果第一个元素选择5或者6,就不能保证选取的3个元素组合满则上面的限制
- 假设第一个元素选取的是2,那么第二个元素只能从[3,4,5]中选取,原因同上
- 假设第二个元素选取的是4,那么第三个元素只能从[5,6]中选取,原因同上
1 class Solution { 2 public: 3 vector<vector<int> > combine(int n, int k) { 4 vector<vector<int> >res; 5 vector<int>tmpres; 6 helper(1,n,k,tmpres,res); 7 return res; 8 } 9 10 //从[left, right]范围内选取k个数,tmpres是一个临时组合 11 void helper(int left, int right, int k, vector<int> &tmpres, vector<vector<int> >&res) 12 { 13 if(k == 0) 14 { 15 res.push_back(tmpres); 16 return; 17 } 18 for(int i = left; i <= right-k+1; i++) 19 { 20 tmpres.push_back(i); 21 helper(i+1, right, k-1, tmpres, res); 22 tmpres.pop_back(); 23 } 24 } 25 };
算法3:非递归的实现。回想一下前面求集合的子集问题,这两个问题都是某个元素而言,选择或者不选择。只是组合问题对子集的大小限制为k,因此我们可以在求子集问题的基础上有如下代码(具体可以先参考子集问题的博文): 本文地址
class Solution {
public:vector<vector<int> > combine(int n, int k) {vector<vector<int> >res;vector<vector<int> >vec(1);for(int i = 1; i <= n; i++){int len = vec.size();vector<int> tmp;for(int j = 0; j < len; j++){tmp = vec[j];tmp.push_back(i);if(tmp.size() == k)res.push_back(tmp);else vec.push_back(tmp);}}return res;}
};
算法4:基于位操作,这里我们主要借助一个二进制操作“求最小的、比x大的整数M,使得M与x的二进制表示中有相同数目的1”,如果这个操作已知,那么我们可以设置一个初始整数bit,bit的低位第1~k个二进制位为1,其余二进制位为0,bit的二进制表示一种组合,然后调用上述操作求得下一个bit,bit的最大值为:bit从低位起第n-k+1~n位等于1,其余位等于0,即(1<<n) - (1<<(n-k),关于这个方法具体可以参考给力!高效!易懂!位运算求组合
1 class Solution { 2 public: 3 vector<vector<int> > combine(int n, int k) { 4 vector<vector<int> >res; 5 vector<int>tmpres; 6 for(int bit = (1<<k) - 1; bit <= (1<<n) - (1<<(n-k)); bit = NextN(bit))//注意bit的最大值为(1<<n) - (1<<(n-k)即选择n的前k个 7 { 8 tmpres.clear(); 9 for(int i = 0; i < n; i++) 10 { 11 if(bit & (1<<i)) 12 tmpres.push_back(i+1); 13 } 14 res.push_back(tmpres); 15 } 16 return res; 17 } 18 //返回最小的、比N大的整数M,使得M与N的二进制表示中有相同数目的1 19 int NextN(int N) 20 { 21 int x = N&(-N); 22 int t = N+x; 23 return t | ((N^t)/x)>>2; 24 } 25 };
算法5:算法之排列与组合算法这篇文章中还介绍了另一种基于二进制的做法,描述如下:
本程序的思路是开一个数组,其下标表示1到n个数,数组元素的值为1表示其代表的数被选中,为0则没选中。
首先初始化,将数组前n个元素置1,表示第一个组合为前n个数。
然后从左到右扫描数组元素值的“10”组合,找到第一个“10”组合后将其变为“01”组合,同时将其左边的所有“1”全部移动到数组的最左端。
当第一个“1”移动到数组的n-m的位置,即n个“1”全部移动到最右端时,就得到了最后一个组合。
例如求5中选3的组合:
1 1 1 0 0
//1,2,3
1 1 0 1 0
//1,2,4
1 0 1 1 0
//1,3,4
0 1 1 1 0
//2,3,4
1 1 0 0 1
//1,2,5
1 0 1 0 1
//1,3,5
0 1 1 0 1
//2,3,5
1 0 0 1 1
//1,4,5
0 1 0 1 1
//2,4,5
0 0 1 1 1
//3,4,5
【版权声明】转载请注明出处:http://www.cnblogs.com/TenosDoIt/p/3461555.html
转载于:https://www.cnblogs.com/TenosDoIt/p/3461555.html
LeetCode:Combinations相关推荐
- LeetCode Combinations (组合)
问题:给出n,k,要求输出从1到n选取k个数的所有组合 思路:使用dfs,第一层是从1到n中选取一个数,第二层是从基于上一层选取的数+1到n中选取一个数,依次类推. 具体代码参考: https://g ...
- [Leetcode] Combinations 组合数
Combinations Given two integers n and k, return all possible ombinations of k numbers out of 1 ... n ...
- Leetcode Combinations
Given two integers n and k, return all possible combinations of k numbers out of 1 ... n. For exampl ...
- leetcode combinations java_[LeetCode][Java] Combinations
题目: Given two integers n and k, return all possible combinations of k numbers out of 1 ... n. For ex ...
- LeetCode - Combinations
题目: Given two integers n and k, return all possible combinations of k numbers out of 1 ... n. For ex ...
- [LeetCode] Combinations
要求 给定两个整数(n,k),返回长度为k,从1到n的所有组合(注意1.组合没有顺序 2. [2,3]和[3,2]为同一组,取前者小于后者的那一组). 例如(4,2),结果为: [[2,4],[3, ...
- LeetCode 解题报告索引
最近在准备找工作的算法题,刷刷LeetCode,以下是我的解题报告索引,每一题几乎都有详细的说明,供各位码农参考.根据我自己做的进度持续更新中...... ...
- LeetCode 17. Letter Combinations of a Phone Number--笔试题--C++,Python解法
题目地址:Letter Combinations of a Phone Number - LeetCode Given a string containing digits from 2-9 incl ...
- leetcode算法题--Combinations
原题链接:https://leetcode.com/problems/combinations/ class Solution {public:vector<vector<int>& ...
最新文章
- fusionchart图表遮挡Ext下拉控件或日期控件解决办法(IE下有问题firefox与chrome正常)...
- linux 线程 pthread create 源码 剖析
- 什么是Session共享?请举出使用场景
- 【CV】给AI一张高清照片,分分钟还你细节满满的3D人体模型,GitHub标星4.4k | 在线可玩...
- 企业建设呼叫中心需要考虑哪些因素
- QT5基础操作(一)
- centos7安装Nginx 配置及反向代理
- 【odoo15】如何使用 python xmlrpc 连接 odoo
- EnableViewState和ViewStateMode差别详解
- 浅谈机器学习评估中的穿越问题
- 使用stress进行压力测试
- git pull git push 报spawn ssh错误,vscode更换默认终端
- 部署点评Cat监控项目
- HTML图片映射矩形坐标,HTML图片热区map area的用法(转载)
- Elasticsearch Nested类型深入详解
- 关于VS2017许可证过期问题
- [C语言数据结构]栈
- 电路设计实例(防止DC电源反接的方法)
- 2023年1月伊凡梳理如何快速安装git并且配置本地gitee账号权限方便拉代码
- 2019ICPC上海网络赛A 边分治+线段树