1.Problem
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], ]
2.Pre-Thought
采用01反转法,可解决该问题。(请参考:http://www.360doc.com/content/10/1102/16/4095212_66011065.shtml)
3.Difficulty
3.1Runtime Error: Last executed input:
出现该问题的原因是未考虑while循环的终止条件,使得迭代器溢出。这是一个很深刻的教训!!!
// 寻找反转位置
// !!!谨记:迭代器的值最大为end(),要及时跳出循环
while(!(pre == 1 && cur == 0))
{
pre = cur;
cur = *it++;
first++;
if(!is_first)
first_one++;
if(cur == 1)
{
one_num++;
if(!is_first)
is_first = true;
}
if(it == st.end())
break;
}
3.2扫描结束的终止条件
// 如果first = n,直接退出
if(first_one != n-k+1)
4.Coding
<pre name="code" class="cpp">#include<iostream>
#include<vector>
using namespace std;
class Solution
{
public:
vector<vector<int> > combine(int n, int k)
{
// 对10集合和结果集合进行初始化
vector<int> sub_result;
vector<vector<int> > result;
vector<int> st(k, 1);
st.insert(st.end(), n - k, 0);
int i;
// 对每一次扫描所需的变量进行声明
int pre = -1;// 扫描的前一个数
int cur = -1;// 当前扫描的数
int first = -1;// 记录第一个10的位置,这是10反转的位置
int first_one = 1;// 记录第一个1的位置
bool is_first = false;// 判断1是否是第一次出现
int num = 0;// 输出当前的数
int k_num = 0;// 记录1的个数
int one_num = 0;// 记录10组合前面1的个数
int zero_num = 0;// 记录10组合前面0的个数
vector<int>::iterator it;
vector<int>::iterator b;
vector<int>::iterator e;
// 如果k=1,分别输出1,2,.....n即可
if(k == 1)
{
for(i = 1; i <= n; i++)
{
sub_result.push_back(i);
result.push_back(sub_result);
sub_result.clear();
}
return result;
}
// 如果n=k,直接输出1,2......n即可
if(n == k)
{
for(i = 1; i <= n; i++)
{
sub_result.push_back(i);
}
result.push_back(sub_result);
sub_result.clear();
return result;
}
// 初始化状态,输出1,2,3......k
for(i = 1; i <= k; i++)
{
sub_result.push_back(i);
}
result.push_back(sub_result);
do
{
// 对每一次内层循环进行初始化
sub_result.clear();
pre = -1;
it = st.begin();
cur = *it++;// 从第一个数开始扫描
first = 0;
first_one = 1;
is_first = false;
one_num = 0;
zero_num = 0;
if(cur == 1)
{
one_num = 1;
first_one = 1;
is_first = true;
}
// 寻找反转位置
// !!!谨记:迭代器的值最大为end(),要及时跳出循环
while(!(pre == 1 && cur == 0))
{
pre = cur;
cur = *it++;
first++;
if(!is_first)
first_one++;
if(cur == 1)
{
one_num++;
if(!is_first)
is_first = true;
}
if(it == st.end())
break;
}
// 如果first = n,直接退出
if(first_one != n-k+1)
{
// 反转
*(it - 1) = 1;
*(it - 2) = 0;
// 将10组合前面的1全部置前
one_num--;// 01组合前面1的个数
zero_num = first - one_num - 1;// 01组合前面0的个数
b = st.begin();
e = it - 2;
st.erase(b, e);// 先删除10组合前面的所有数
b = st.begin();
st.insert(b, zero_num, 0);// 在10组合前面先插入zero_num个0
b = st.begin();// 记得每一次更新首元素时,要更新迭代器
st.insert(b, one_num, 1);// 在10组合前面再插入one_num个1
// 对10元素集合进行遍历,将1所在位置的数存入sub_result集合中
it = st.begin();
num = 0;
k_num = 0;
while(k_num != k)
{
num++;
if(*it++ == 1)
{
k_num++;
sub_result.push_back(num);
}
}
result.push_back(sub_result);
}
}while(first_one != n-k+1);
return result;
}
};
int main()
{
int n = 4;
int k = 2;
vector<vector<int> > result;
Solution sol;
result = sol.combine(n, k);
vector<vector<int> >::iterator it1 = result.begin();
while(it1 != result.end())
{
vector<int> temp = *it1++;
vector<int>::iterator it2 = temp.begin();
while(it2 != temp.end())
{
cout<<*it2++<<" ";
}
cout<<"Lenght:"<<temp.size()<<endl;
}
cout<<"Result:"<<result.size()<<endl;
return 0;
}