【问题标题】:Duplicate permutations in Java programJava程序中的重复排列
【发布时间】:2015-06-26 17:32:45
【问题描述】:

我阅读了一种用于递归生成字符串排列的算法。

invoke the function with j = 1
    if (j == length of string)
        print the string and return
    else
        for (i = j to length of string)
            interchange jth character with ith character
            call function on j + 1

我使用 java 实现了如下:

class PERMUTATION {
    private int count = 1;
    private char[] arr = {'A', 'B', 'C'};

    public void perm(int k) {
        if (k == 3)  {
            System.out.print(count+++".");
            for (int i = 0; i < 3; ++i)
                System.out.print(arr[i]+"  ");
            System.out.println();
            return;
        }
        for (int i = k; i <= 3; ++i) {
            /*interchanging ith character with kth character*/
            char c = arr[i - 1];
            arr[i - 1] = arr[k - 1];
            arr[k - 1] = c;
            perm(k + 1);
        }
    }

    public static void main(String []args) {
        System.out.println("the permutations are");
        PERMUTATION obh=new PERMUTATION();
        obh.perm(1);
    }
}

但是我的程序产生了重复的排列。为什么?

【问题讨论】:

    标签: java recursion permutation


    【解决方案1】:

    如果“源”数组保持不变,则此算法有效,因此每个索引都会被正确处理。

    让我们看看你的代码的输出:

    1.A B C
    2.A C B
    3.C A B
    4.C B A
    5.A B C
    6.A C B

    如您所见,在第 1 次迭代中。 3,它应该将 B 移动到第一个索引,而是移动 C,因为您已经将 B 移动到了不同的位置。 由于这个事实,B 没有机会进入第一个索引,只会在 2 到 3 之间“反弹”。

    您的主要问题是,您正在更改“源”数组。如果你避免这种情况,那么你的算法就可以正常工作:

    class PERMUTATION {
        private int count = 1;
    
        public void perm(char[] arr, int k) {
            if (k == 3) {
                System.out.print(count++ + ".");
                for (int i = 0; i < 3; ++i)
                    System.out.print(arr[i] + "  ");
                System.out.println();
                return;
            }
            char[] arr2 = arr.clone(); // clone the passed array, so we don't mess it up
            for (int i = k; i <= 3; ++i) {
                /* interchanging ith character with kth character */
                char c = arr2[k - 1];
                arr2[k - 1] = arr2[i - 1];
                arr2[i - 1] = c;
                perm(arr2, k + 1);
            }
        }
    
        public static void main(String[] args) {
            System.out.println("the permutations are");
            PERMUTATION obh = new PERMUTATION();
            obh.perm(new char[] {'A', 'B', 'C'}, 1); // pass the original array
        }
    }
    

    然后输出将是:

    1.A B C
    2.A C B
    3.B A C
    4.B C A
    5.C A B
    6.C B A

    顺便说一句:请注意Java Naming Conventions,所以不要给你的班级打电话PERMUTATION,改用Permutation

    【讨论】:

    • 这是否意味着这个算法的空间复杂度是O(n)?
    • @Dante 我想它有点多......也许 O(2n)(由于 6 个最终结果)甚至 O(3n),因为我们需要一些递归,在我们找到之前一个“最终结果”。我们在每个perm 调用中克隆源数组,所以会有很多克隆,但是它们的生命周期相对较短,因此可以快速进行垃圾回收。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-13
    • 1970-01-01
    • 2019-07-02
    • 1970-01-01
    相关资源
    最近更新 更多