- 如果我有一张索引卡,字母C写在一边,S在另一边。我如何编写一个递归方法来打印每个使用C和S的卡丢弃的sessoin。例如:如果我放弃它4次,所有可能的方法都按照以下特定顺序删除它:
SCSC SCSS SSCC SSCS SSSC SSSS
答案 0 :(得分:0)
因此,如果您意识到卡片翻转实际上只是在二进制中向上计数,那么这个问题实际上要简单得多。
考虑到这一点,您可以跟踪 X 位长号码(其中 X 是您想要跟踪的牌数)然后通过检查以查看1(S
)或0(C
)的位置来打印卡片。
执行此操作后,请检查所有位置是否为1。如果他们这样做,退出递归。如果没有,请在号码中添加一个并再次运行该功能。
修改
如果您事先知道数字中的位数(足够容易计算),您可以使用位移(>>
将是最好的)。例如,你可以通过快速循环来查看数字并检查每个位置。
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
希望您可以使用上述内容并根据递归问题的代码进行调整。
答案 1 :(得分:0)
实际上相当简单:
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);
}
这本质上是一种递归编写的迭代算法。