我正在开展一个项目。我在Interwebz上找到了关于排列的代码。我想用它作为编写我自己的代码的基础。但是,我真的不明白代码中发生了什么。有人可以帮我解释一下代码究竟在做什么吗?
public void permutations(String prefix, String s) {
int n = s.length();
if (n == 0)
System.out.println(prefix);
else {
for(int i = 0; i < n; i++){
permutations(prefix + s.charAt(i), s.substring(0, i) + s.substring(i+1, n));
}
}
}
答案 0 :(得分:2)
方法permutations
将字符串prefix
和字符串s
作为参数。
int
类型n
设置为字符串s
的长度。 (字符串的长度是它包含的字符数。)
现在我们转到if
- else
语句。 if
语句说,如果s
的长度为0,即s
是一个空字符串且不包含任何信息,那么我们只是打印字符串{{ 1}}而不是控制台。然后,该方法将跳过prefix
部分并在else
方法之后执行代码。
如果不满足permutations
语句的条件,我们将运行if
语句,对于字符串else
中的每个字符,我们将追加(添加) )s
末尾的那个字符,例如,如果prefix
最初是“你好”而字符是'U',我们会prefix
为“helloU”。在我们完成附加prefix
中的所有字符后,我们将使用结果作为新的s
字符串。
对于另一个参数,字符串prefix
,我们将使用字符串的一部分,从字符0(包括)到位置s
的字符(不包括)。请注意,String索引从0开始并向上移动(String的长度为-1)。我们还将字符串的一部分从位置i + 1(包括)的字符转换为字符串i
中的最后一个字符。我们将使用此结果作为新的s
字符串。
然后我们将再次调用该方法,然后如果满足s
条件,则该方法将再次使用新定义的字符串执行。这将继续循环,直到else
条件不满足为止,此时方法将停止运行,我们将继续执行下一部分代码(如果存在)。
答案 1 :(得分:2)
p(String prefix, String s)
从s
中取出1个字符并将其添加到prefix
并递归继续,直到s
为空。
s.charAt(i), s.substring(0, i) + s.substring(i+1, n)
部分从s
中提取字符。
假设s = "Magic!"
和i = 3
然后charAt(i) = 'i'
,s.substring(0, i) = "Mag"
和s.substring(i+1, n) = c!"
。将Magic!
转换为i
和Magc!
。下次使用i = 4
进行循环时,会产生c
+ Magi!
。因为它为s
中的每个字符执行此操作,因此每个字符都将在其中一个递归步骤中位于前面。
调用层次结构看起来像这样
/ p("ab", "c") - "abc"
/- p("a", "bc") x
/ \ p("ac", "b") - "acb"
/
/ / p("ba", "c") - "bac"
p("", "abc") x ---- p("b", "ac") x
\ \ p("bc", "a") - "bca"
\
\ / p("ca", "b") - "cab"
\- p("c", "ab") x
\ p("cb", "a") - "cba"
^-- 1st for loop ^- 2nd for ^- 3rd one prints
答案 2 :(得分:1)
permutations(prefix + s.charAt(i), s.substring(0, i) + s.substring(i+1, n));
实际上,这种置换算法正在使用
的思想Switching current character with ith character.
假设我们有一个字符串abc
。所以它的排列是:
abc, acb, bac, bca, cab, cba
我们可以发现acb
只是在b
中使用前缀c
切换abc
和a
。而bca
只是在c
中使用前缀a
切换bac
和b
。
然后我们只是使用相同的想法来递归地解决排列问题。
答案 3 :(得分:1)
这是一些非常令人困惑的代码,原因有两个:
prefix
参数:您应该在第一个参数中使用空字符串调用此函数,例如permutations("", "ab")
以打印"ab"
的所有(两个)排列。s.substring(0, i) + s.substring(i+1, n)
进行递归调用:请注意,java的String.substring(x,y)
将不包含第y个字符。所以这相当于传递s
并删除了第y个字符。现在想想当您逐步执行for
循环时会发生什么:第一个参数变为""
与"a"
连接,即"a"
,第二个参数变为{{ 1}}删除第一个字符,即s
。在下一个递归子查询中,"b"
变为prefix
,第二个参数变为空字符串"ab"
。因此基础案例""
会被点击,我们会打印结果n == 0
。
现在我们转到for循环的下一个迭代"ab"
。现在我们在递归子句的第一个参数中传递i == 1
,在第二个参数中传递"b"
。在下一个递归子查询"a"
变为prefix
且"ba"
为0,因此再次基本情况:打印s.length
。
这很聪明,但难以理解。