组合和置换算法(递归)

我正在从事Java任务,我绝对难过。

问题是:

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

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

  2. 显示所有可能的方法,您可以在订单重要时填写Y信封,并允许重复hint: X^Y

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

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

例如,在情况(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信封(ex: X=5, Y=3) {1, 2, 3}. 用最高卡{1, 2, 5} 1,2,5 {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 { } } } 

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

你的老师要你使用递归。

对于给定的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> 。 当y=0 ,返回一个带有一个元素的Set (一个空Set )。 y=1 ,返回一个Set ,通过向较大集合中的每个集合添加一个元素来构建一堆Set (在y=1的情况下, Set为空,依此类推)。

使用“ Set而不是“ List因为您要确保没有重复项。

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

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

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

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

打印数组

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

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

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

访问:http://www.bearcave.com/random_hacks/permute.html

我不知道如何在JAVA中做到这一点,但我旧C代码的片段可能有助于达到目的。

 #include  //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; }