组合和置换算法(递归)
我正在从事Java任务,我绝对难过。
问题是:
使用Recursion编写一个函数来执行以下操作:您有X个不同的卡。 你只有Y信封。 Y小于或等于X.对于任何给定的X和Y值,
-
显示所有可能的方式,您可以在订单不重要时填写Y信封并且不允许重复。
hint: X! / (( XY)! * Y!)
-
显示所有可能的方法,您可以在订单重要时填写Y信封,并允许重复
hint: X^Y
-
显示订单重要时可以填写Y信封的所有可能方式,并且不允许重复提示:
X! / (X – Y)!
X! / (X – Y)!
-
当订单不重要时,显示所有可能的填充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_1
到card_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; }