组合和置换算法(递归)

时间:2012-11-04 02:49:48

标签: java recursion permutation combinations repeat

我正在从事Java任务,我绝对难以接受。

问题是:

使用Recursion编写一个函数来执行以下操作:您有X个不同的卡。你只有Y信封。 Y小于或等于X.对于X和Y的任何给定值,

  1. 显示订单不重要且不允许重复时填写Y信封的所有可能方式。 hint: X! / (( X-Y)! * Y!)

  2. 显示订单重要且允许重复时填写Y信封的所有可能方式hint: X^Y

  3. 显示订单重要时可以填写Y信封的所有可能方式,并且不允许重复提示:X! / (X – Y)!

  4. 显示订单不重要时可以填写Y信封的所有可能方式,并允许重复提示:(X + Y – 1)! / (Y! * (X – 1)!)

  5. 例如,在情况(1),if X = {J, Q, K, A) and Y = 3下,输出应为:{J,Q,K} {J,Q,A} {J,K,A} {Q,K,A}.

    我不希望任何人发布任何代码,我也不希望任何人为我解决这个问题!我希望,一旦我完成了第一部分(问题a),它将解锁洪水门。有人可以提供一些指导来制定伪码算法,这是我能得到的:

    随着卡(ex: X=5, Y=3) {1, 2, 3}.的增加,按顺序填写Y信封 用最高卡{1, 2, 5}替换最高信封,递减直到我们找到它的原始值{1, 2, 4}。 对每个信封执行此操作,从最高到最低(数字尚未使用){1, 5, 4} {1, 3, 4} {5, 3, 4} {2, 3, 4}.

    因为缺少3种组合{1, 5, 3} {3, 4, 5} {5, 3, 2}.

    我会感激任何帮助,因为这是我将重新进行的任务,我不想要解决方案,我希望自己能够帮助解决问题。 谢谢!

    编辑:我已经尝试了所有3个解决方案,我仍然没有得到它。这就是我到目前为止所得到的:

    public static void comboNoRep(String[] a, int y, boolean[] used)
    {
    
        if(y == 0) {
            // found a valid solution.
            System.out.println(result);
        }
    
        for(int i=0; i<a.length; i++) {
            if(!used[i]) {
                used[i] = true;
                result = result + a[i];
                comboNoRep(a, y - 1, used);
                result = result + " ";
                used[i] = false;
            }
            else {
            }
        }
    
    }
    

    任何人都可以帮助指出我的缺陷吗?

4 个答案:

答案 0 :(得分:1)

您的老师希望您使用递归。

对于给定的X,如果Y为零,答案是什么?使用您的代码解决这个问题。

答案是什么,对于给定的X,如果我给你解决Y =一些随机整数n免费,n + 1的解决方案是什么?换句话说,如果我告诉你X = 5的解,Y = 3是{{...},{...},...},你能否轻松找出X = 5的解, Y = 3 + 1 = 4?

以下是一个完全不同问题的示例:

让我们说你知道前两个Fibonacci数字是1和1.然后找到下一个很容易,对吗?它是2.现在让我们说你知道前两个是1和2,下一个是3!如果前两个是2和3,则下一个是5!

一些伪代码:

public int fib(int stop) {
     if (stop < 2) return 1;
     return fibHelp(stop - 2, 1, 1);
}

public int fibHelp(int stop, int oneBelow, int twoBelow) {
   if (stop == 0) return oneBelow;

   return fibHelp(stop - 1, oneBelow + twoBelow, oneBelow);
}

了解fibHelp如何调用自身?这是递归!只要确保你有一个停止条件(我的if语句)。

针对您的具体问题,请不要返回void,而应让comboNoRep返回Set<Set<Integer>>。在y=0时,请使用一个元素(空Set)返回Sety=1,通过向较大集合中的每个集合添加一个元素,返回构建一堆Set的{​​{1}} Set y=1是空的,等等。)

使用Set而非Set,因为您要确保没有重复项。

答案 1 :(得分:0)

您必须探索所有可能的路线:

创建一个“解决方案”的空列表

对于每张卡片a,您的第一套解决方案首先将卡片放在每个信封中 - x * y解决方案

对于您挑选的每张卡片:重复,从同一组卡片中移除您使用的卡片,直到您完成解决方案并且将其放入阵列中时用完卡片

打印数组

答案 2 :(得分:0)

对于问题一,假设您的卡片被命名为card_1card_x。请注意,填充Y信封的每种可能方式都包括card_1或不包括{{1}}。如果是这样,你就减少了用2到X卡填充Y-1信封的问题;如果没有,你就把问题减少到用信用卡2到X填充Y信封。

希望这足以帮助你而不是太多。祝你好运!

答案 3 :(得分:0)

您可以将Exeter算法用于第一部分。有关更多信息,请参阅以下链接:

Visit Here: http://www.bearcave.com/random_hacks/permute.html

我不知道如何在JAVA中执行此操作,但我旧C代码中的代码段可能会达到此目的。

#include <stdio.h>

//Print Function
void print(const int *arr, const int size)
{
    int i;

    if (arr != 0) 
    {
        for (i = 0; i < size; i++)
            printf("%d ", arr[i]);
        printf("\n");
    }
}

//Permute Function
void permute(int *arr, const int start, const int sets, const int len)
{  
    int i,tmp;

    if (start == sets-1)
        print(arr, sets);
    else
    {
        for (i = start; i < len; i++)
        {
            tmp = arr[i];

            arr[i] = arr[start];
            arr[start] = tmp;

            permute(arr, start+1, sets, len);   //<-- Recursion

            arr[start] = arr[i];
            arr[i] = tmp;
        }
    }
}

int main()
{
  int sets,arr[] = {1, 2, 3, 4, 5};

  //Accept Number Of Sets To Form
  printf("Enter Number Of Sets: ");
  scanf("%d",&sets);

  //Call Permute Function
  permute(arr, 0, sets, sizeof(arr)/sizeof(int));

  return 0;
}