4

我正在尝试打印出 nCr 的所有可能性,这是顺序无关紧要时的组合。所以 5C1 有 5 种可能性:1 , 2, 3, 4, 5。 5C2 有 10 种可能性: 1 2, 1 3, 1 4, 1 5, 2 3, 2 4, 2 5, 3 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
4

5 回答 5

7

这个怎么样:

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;
    }
}

对我来说,这个解决方案的关键是将问题视为一个编号系统,并且您想将一个数字加一,每次达到上限时,您只需将多余的部分带到左边,然后......您只需需要正确实现递增算法...

于 2011-10-03T06:56:51.853 回答
4

您的代码偏离预期的第一点是:

...
1 2 5 
1 2 5    <-- first bad output
1 3 5
...

所以问自己三件事:

  • 在给定变量状态的那行代码中应该发生什么?

  • 为什么我的代码不完全那样做?

  • 必须改变什么才能实现这一目标?

第一部分的答案是这样的:

  • 它应该增加2to3并且应该将以下数字设置为 4, , 5...类似于.nums

第二和第三部分又是你的部分。

BTW:当您因为需要更多帮助而回来时,请详细说明您到目前为止所推断的内容清理并缩短问题。

于 2011-10-02T18:09:39.063 回答
1

好的......当我们知道我们需要循环而不是它们的数量时,解决方案是什么?递归...您需要使用递归实现。记住这一点:任何时候,你都需要循环,但嵌套循环的数量只能在运行时知道,根据问题的具体参数,你应该使用递归方法......我会给你一些时间试试自己动手,我会回来给你最终的实现......

于 2011-10-02T15:06:24.143 回答
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;
}
于 2013-02-27T11:01:24.103 回答
0

功能的布局printCombination()似乎是错误的。while 循环将迭代两次,forcount = 1count = 2

当 时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

于 2011-10-02T14:26:04.530 回答