private static void swap(char[] str, int i, int j){
char tmp = str[i];
str[i] = str[j];
str[j] = tmp;
}
public static void permute(String str){
permute(str.toCharArray(), 0, str.length());
}
private static void permute(char[] str, int low, int high){
if(low == high){
System.out.println(str);
} else {
for(int i = low; i < high; i++){
swap(str, low, i);
permute(str, low+1, high);
swap(str, low, i);
}
}
}
我为字符串置换实现了一个递归方法。但我有一个问题:如何通过使用归纳来证明此代码的正确性?我真的不知道。
答案 0 :(得分:0)
首先,您必须具体说明正确性的含义(即您要检查代码的规范;另请参阅https://stackoverflow.com/a/16630693/476803)。让我们假设正确性在这里意味着
permute
的每个输出都是给定字符串的排列。
然后我们可以选择执行归纳的自然数。对于递归函数permute
,我们可以选择low
或high
之间或其中某些组合。
在阅读实现时,很明显输出字符串的前缀是其元素不会改变的。此外,该前缀的长度在递归期间增加,因此剩余的后缀(其长度为high - low
)减小。因此,让我们在high - low
上进行归纳(假设low <= high
,这是合情合理的,因为最初我们使用0
表示低high
的某些字符串的长度,以及递归在low == high
)后立即停止。也就是说,我们展示
事实:
permute(str, low, high)
的每个输出都是high - low
的最后str
个字符的排列。
基本案例:假设high - low = 0
。然后该陈述是真实的,因为它必须保留最后0
个字符(即,没有)。
步骤案例:假设high - low = n + 1
。此外,作为归纳假设(IH),我们可以假设该陈述适用于n
。从high - low = n + 1
开始,我们high - (low + 1) = n
(因为high
必须严格大于low
才能保留high - low = n + 1
。因此,通过IH,permute(str, low+1, high)
的每个输出都是high - (low + 1)
的最后str
个字符的排列。
现在我们必须要证明某些事情。即通过在permute(str, low+1, high)
生成的输出中交换low
个str
个字符,low
个字符high
之后的任何字符(最多low
),我们会在high
和0
之间生成字符排列。这一步(我在这里省略,因为我只是想证明你原则上如何使用归纳法)得出结论证明。
最后,通过low
为str.length
和high
permute
实例化上述事实,我们得到了非{}递归str
是{{1}}的排列。
注意:以上证明仅显示每个输出 一个排列。但是,知道实际所有排列都会打印出来也可能会很有趣。