我正在尝试打印出nCr的所有可能性,这些是订单无关紧要时的组合。所以5C1有5种可能性:1,2,3,4,5。5C2有10种可能性:1 2,1 3,1 4,1 5,2 2,3,2,4,5 3,4 4,3 5, 4 5。
我制作的函数可以打印我想要的r = 2,r = 3和r = 4,我有点看模式,但我似乎无法为变量r创建一个工作方法:
public void printCombinationsChoose2(int n, int k) //for when k = 2
{
for (int a = 1; a < n; a++)
{
for (int b = a + 1; b <= n; b++)
{
System.out.println("" + a + " " + b);
}
}
}
public void printCombinationsChoose3(int n, int k) //for when k = 3
{
for (int a = 1; a < n - 1; a++)
{
for (int b = a + 1; b < n; b++)
{
for (int c = b + 1; c <= n; c++)
{
System.out.println("" + a + " " + b + " " + c);
}
}
}
}
public void printCombinationsChoose4(int n, int k) //for when k = 4
{
for (int a = 1; a < n - 2; a++)
{
for (int b = a + 1; b < n - 1; b++)
{
for (int c = b + 1; c < n; c++)
{
for (int d = c + 1; d <= n; d++)
{
System.out.println("" + a + " " + b + " " + c + " " + d);
}
}
}
}
}
public void printCombinations(int n, int k) //Doesn't work
{
int[] nums = new int[k];
for (int i = 1; i <= nums.length; i++)
nums[i - 1] = i;
int count = 1;
while (count <= k)
{
for (int a = nums[k - count]; a <= n; a++)
{
nums[k - count] = a;
for (int i = 0; i < nums.length; i++)
System.out.print("" + nums[i] + " ");
System.out.println();
}
count++;
}
}
所以我认为我最后一种方法的布局是正确的,但我只是没做正确的事情,因为当我打电话给printCominbations(5, 2)
时,它会打印
1 2
1 3
1 4
1 5
1 5
2 5
3 5
4 5
5 5
应该是我之前所说的5C2。
修改
最后一个例子很糟糕。这是一个更好的例子来说明它做错了什么:printCombinations(5, 3)
给出了这个:
1 2 3
1 2 4
1 2 5
1 2 5
1 3 5
1 4 5
1 5 5
1 5 5
2 5 5
3 5 5
4 5 5
5 5 5
我如何得到它:
1 2 3
1 2 4
1 2 5
1 3 4
1 3 5
1 4 5
2 3 4
2 3 5
2 4 5
3 4 5
答案 0 :(得分:6)
这个怎么样:
public class Test {
public static void main(final String[] args) {
print_nCr(7, 4);
}
public static final void print_nCr(final int n, final int r) {
int[] res = new int[r];
for (int i = 0; i < res.length; i++) {
res[i] = i + 1;
}
boolean done = false;
while (!done) {
System.out.println(Arrays.toString(res));
done = getNext(res, n, r);
}
}
/////////
public static final boolean getNext(final int[] num, final int n, final int r) {
int target = r - 1;
num[target]++;
if (num[target] > ((n - (r - target)) + 1)) {
// Carry the One
while (num[target] > ((n - (r - target)))) {
target--;
if (target < 0) {
break;
}
}
if (target < 0) {
return true;
}
num[target]++;
for (int i = target + 1; i < num.length; i++) {
num[i] = num[i - 1] + 1;
}
}
return false;
}
}
对我来说这个解决方案的关键是将问题看作一个编号系统,你想要增加一个数字,每当你达到一个上限时,你只需将多余的数据带到左边,然后......你只需要正确实现增加算法......
答案 1 :(得分:4)
您的代码偏离期望的第一点是:
... 1 2 5 1 2 5 <-- first bad output 1 3 5 ...
所以问问自己三件事:
在具有给定变量状态的代码行中应该发生什么?
为什么我的代码不完全是那个?
要实现这一目标必须改变什么?
第一部分的答案是这样的:
2
增加到3
,它应该设置以下数字
4
,5
,... 与nums
的初始化相似。第二部分和第三部分再次成为你的一部分。
顺便说一句:当你回来因为需要更多帮助时,请详细解释你到目前为止所推断的内容和清理并缩短问题。答案 2 :(得分:1)
好的......当我们知道我们需要循环,而不是它们的数量时,解决方案是什么?递推... 您需要使用递归实现。请记住:ANYTIME,你需要循环,但嵌套循环的数量只能在运行时知道,根据问题的具体参数,你应该使用递归方法...我会给你一些时间来尝试你自己,我会回来给你最后的实施......
答案 3 :(得分:1)
我在c ++中完成了
#include <iostream>
using namespace std;
#define ARR_LIMIT 100
int arr[ARR_LIMIT];
void _ncr(int N,int R, int n,int r , int start )
{
if(r>0)
{
for(int i = start ; i <= start + (n-r); i++)
{
arr[R-r] = i;
_ncr(N,R,N-i, r-1, i+1 );
}
}
else
{
for(int i=0;i<R;i++)
{
cout << arr[i] << " ";
if(i==R-1)
cout<<"\n";
}
}
}
void ncr(int n,int r)
{
//Error checking of parameters
bool error = false;
if( n < 1)
{
error = true;
cout<< "ERROR : n should be greater 0 \n";
}
if( r < 1)
{
error = true;
cout<< "ERROR : r should be greater 0 \n";
}
if(r > n)
{
error = true;
cout<< "ERROR : n should be greater than or equal to r \n";
}
// end of Error checking of parameters
if(error)
return;
else
_ncr(n,r,n,r,1);
}
int main()
{
int n,r;
cout << "Enter n : ";
cin >> n;
cout << "Enter r : ";
cin >> r;
ncr(n,r);
return 0;
}
答案 4 :(得分:0)
函数printCombination()
的布局似乎错了。对于count = 1
和count = 2
,while循环将迭代两次。
count = 1
时,只有nums[0][here]
中的值会发生变化,因为在这种情况下k - count = 1
。
因此,
1,2
1,3
1,4和
1,5。
当count = 2
时,只有nums[here][1]
中的值会发生变化,因为此处为k - count = 0
。
因此
1,5
2,5
3,5
4,5和
5,5