问候,
上周我说过,很多论坛中的很多话题都提到了各种各样的话题。
排序问题。 上周的小贴士给出了很多答案
排序问题。 另一个“收藏夹”(请注意引号)主题是关于
排列和组合。 本周技巧提示如何排列
以高效的方式生成。 下一个技巧讨论组合如何
有效地生成。
首先,这是一个非常草率的定义:
if a word S < T lexicographically then word S can be found before word T can
be found in a dictionary.
这是包含三个不同字符A,B和C的所有单词
按照字典顺序:ABC,ACB,BAC,BCA,CAB和CBA。 请注意,这是
在字典中找到它们的顺序(如果该字典的编辑者
字典完全认为它们是合法的字典词。
我们算法的核心是尝试在给定当前值的情况下寻找下一个排列
排列。 “下一个”的概念在字典上定义为下一个。
例如,考虑一下ACEDB一词; 接下来的排列是什么
是吗? 经过一番摆弄之后,您可以找出下一个:ADBCE
这是正式(伪代码)完成的方式:
1)对于排列p_0 p_1 ... p_n找到最右边的索引值i这样
p_i <p_(i + 1)。 如果没有找到,我当前的排列是
他们所有的最后排列; 如果是这样,请停止。
对于我们的示例,p_i将是字母C,因为它是最右边的字母
恰好小于它右边的那个:C <E
2)找到最右边的索引j,使p_j> p_i。 请注意,这样的aj可以
如果步骤1)成功,总是可以找到。
对于我们的示例,p_j是字母D,因为它是最右边的字母
恰好大于p_i(D> C)
我们从零(0)开始计数,所以i == 1和j == 3。
3)交换元素p_i和p_j
对于我们的示例,我们交换字母D和C并获得:ADECB
4)反转后缀p_(i + 1)... p_n
对于我们的示例,我们反转ECB并获得ADBCE,这恰好是下一个
当前排列ACEDB的排列。
注意,我们不需要任何递归; 只是循环索引和
一点测试。 记住上一篇技巧文章中的Sortable接口
星期? 这里又是:
public interface Sortable {
int length();
int compare(int i, int j);
void swap(int i, int j);
}
看来我们可以再次使用该接口,即我们需要进行比较
不同的东西,我们需要知道排列的长度,我们需要
才能交换东西。 请注意,我们保留了这些“事物”的概念
尽可能地再模糊。
让我们将此接口用于置换算法。 四个步骤
我们的伪代码算法(见上文)可以很容易地实现如下:
public static Sortable permute(Sortable s) {
int i, j;
// step 1
for (i= s.length()-1; --i >= 0;)
if (s.compare(i, i+1) < 0)
break;
if (i < 0) return null;
// step 2
for (j= s.length(); --j > i;)
if (s.compare(i, j) < 0)
break;
// step 3
s.swap(i, j);
// step 4
for (j= s.length(); ++i < --j;)
s.swap(i, j);
return s;
}
这些注释仅涉及伪代码算法的步骤。
方法
上面的方法使用Sortable来生成下一个排列(如果有),并且
并不真正知道它实际上在操纵什么。 相同的优势
如先前的TOTW所示,该算法再也不关心
关于构造下一个排列的实际操作。
如果不存在下一个排列,则此方法返回null,否则返回
返回Sortable对象中的下一个排列。
为了方便起见,您可以将其直接复制并粘贴到您的私人
再次介绍技巧,这是整个类的定义。 注意该类
只是一个实用程序类,即不必具有“ Permuter”对象
周围; 该类本身没有任何状态,仅具有功能。
这是完整的课程:
public final class Permute {
private Permute() { }
public static Sortable permute(Sortable s) {
// code as above
}
}
请注意,当排列包含重复项时,此算法也可以正常工作
元素; 例如,对于第一个排列AAB,将产生下一个排列:
ABA和BAA。
这是一个练习上述实用程序类的小类:
public class MySortable implements Sortable {
private String[] array;
private MySortable(String array) { this.array= array; }
public int length() { // interface implementation
return array.length;
}
public int compare(int i, int j) { // interface implementation
return array[i].compareTo(array[j]);
}
public void swap(int i, int j) { // interface implementation
String t= array[i]; array[i= array[j]; array[j]= t;
}
public void print() {
for (int i= 0; i < array.length; i++)
System.out.print(array[i]+" ");
System.out.println();
}
public static void main(String[] args) {
MySortable s= new MySortable(new String[] {
"Fred",
"Pebbles",
"Wilma" });
do {
s.print(s);
}
while (s.permute() != null);
}
}
在本周技巧的下一部分中,我们将讨论一些组合。
亲切的问候,
乔斯
From: https://bytes.com/topic/java/insights/629830-permutations