用Java打印所有可能的nCr组合

时间:2011-10-02 13:36:03

标签: java statistics ncr

我正在尝试打印出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

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,它应该设置以下数字 45,... 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 = 1count = 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