排列A

问候,

上周我说过,很多论坛中的很多话题都提到了各种各样的话题。

排序问题。 上周的小贴士给出了很多答案

排序问题。 另一个“收藏夹”(请注意引号)主题是关于

排列和组合。 本周技巧提示如何排列

以高效的方式生成。 下一个技巧讨论组合如何

有效地生成。

首先,这是一个非常草率的定义:


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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值