在java中-如果我有一张索引卡,一侧写有字母C,另一侧写有S。我如何编写一个递归方法来打印每个用 C 和 S 丢弃卡片的 sessoin。例如:如果我放下它 4 次,所有可能的放下它的方法如下:
SCSC SCSS SSCC SSCS SSSC SSSS
其实很简单:
public void flip(List<String> items, int length, String prefix)
{
if (prefix.length() == length) {
items.add(prefix);
return;
}
increments(items, length, prefix + 'C');
increments(items, length, prefix + 'S');
}
如您所见,有两个递归调用,一个用于“C”字符,一个用于“S”字符,递归基本情况是前缀长度是指定的长度(在您的情况下为 4)
像这样调用:
List<String> inc = new LinkedList<>();
increments(inc, 4, "");
for (String s : inc)
System.out.println(s);
哪个输出:
CCCC
CCCS
CCSC
CCSS
CSCC
CSCS
CSSC
CSSS
SCCC
SCCS
SCSC
SCSS
SSCC
SSCS
SSSC
SSSS
这种方法可以很容易地推广到任何字符数组:
public void increments(List<String> items, int length,
String prefix, char[] chars)
{
if (prefix.length() == length) {
items.add(prefix);
return;
}
for (char c : chars)
increments(items, length, prefix + c, chars);
}
List<String> inc = new LinkedList<>();
increments(inc, 4, "", new char[] {'C', 'S'});
for (String s : inc)
System.out.println(s);
这会产生相同的输出。
注意:此方法具有很高的复杂性,O(pow(chars.length, length)),因此尝试以较大的输入大小运行它需要(非常)长时间才能完成。
Integer.toBinaryString(int)
方法按照要求:
public void increments_ibs(List<String> items, int n, int i)
{
if (i >= Math.pow(2, n))
return;
String bs = Integer.toBinaryString(i);
while (bs.length() < n)
bs = "0" + bs;
items.add(bs.replaceAll("0", "C").replaceAll("1", "S"));
increments_ibs(items, n, i+1);
}
这本质上是一种以递归方式编写的迭代算法。
所以这个问题实际上要简单得多,如果你意识到翻牌实际上只是在二进制中向上计数。
考虑到这一点,您可以只跟踪X位长的数字(其中X是您要跟踪的卡片数量),然后通过查看 1 ( S
) 或 0 ( C
)的位置来打印卡片.
完成此操作后,检查所有位置是否都有 1。如果有,退出递归。如果没有,请在数字上加一并再次运行该函数。
编辑
如果您事先知道数字中的位数(很容易计算),您可以使用位移位(>>
这将是最好的)。因此,例如,您可以使用一个快速的 for 循环来遍历数字并检查每个位置。
int cardTracker = 0b0110; //this is 6 in decimal
char[] toPrint = new char[4];
//The 4 here is the length of the binary number
for(int i = 0; i < 4; i++)
{
//This if statement checks if the last number is 0 or 1
if((cardTracker >> ((4 - 1) - i) % 2 == 0)
{
toPrint[i] = 'C';
}
else
{
toPrint[i] = 'S';
}
}
如果您要打印toPrint
.
CSSC
希望您可以使用上述内容并将其调整到您的代码中以解决递归问题。