📜  用示例在Java中实现 next_permutation()

📅  最后修改于: 2022-05-13 01:55:05.970000             🧑  作者: Mango

用示例在Java中实现 next_permutation()

给定一个数组或字符串,任务是找到它在Java中的下一个字典顺序更大的排列。
例子:

Input: string = "gfg"
Output: ggf

Input: arr[] = {1, 2, 3}
Output: {1, 3, 2}

在 C++ 中,有一个特定的函数可以让我们免于编写大量代码。它在头文件#include中。该函数是next_permutation(a.begin(), a.end()) 。它用于将 [first, last) 范围内的元素重新排列为下一个字典顺序更大的排列。一个排列是 N!元素可以采用的可能排列方式(其中 N 是范围内的元素数)。可以根据它们在字典上相互比较的方式对不同的排列进行排序。
显然, Java没有提供任何这样的内置方法。因此,本文讨论如何在Java中实现下一个置换函数及其算法。

天真的方法:生成给定数字/字符串的所有可能排列,将它们存储在一个列表中,然后遍历它以找到给定数字的更大排列。

时间复杂度= O(n!*n) : n!生成所有排列和一个额外的n来遍历并找到更大的排列。

空间复杂度 = O(n!) :存储所有排列。

这种方法非常幼稚且实施起来很复杂。假设我们的数组大小为 100,虽然不是很大,但它会生成 100!排列。这是一个巨大的数字。此外,我们将不得不需要 100 个!存储所有它们的空间,然后遍历它以找到下一个更大的排列。
算法:

这种方法背后的直觉:假设我们有 13542 作为我们的问题,我们必须找到它的下一个排列,观察很明显,当我们从最后一个遍历时,我们看到数字一直在增加,直到 5 和 3 是第一个打破递增顺序的索引,因此,第一步:

  1. 找到最长的非递增后缀并找到枢轴(3 即索引 1 是枢轴)。
  2. 如果后缀是整个数组,则数据没有更高阶的排列(在这种情况下,按照问题要求进行操作,返回 -1 或排序后的数组)。
  3. 找到枢轴的最右边的后继者:再次找到最右边的后继者,从后面开始遍历,当我们遇到大于枢轴的元素时,我们停止,因为它是必需的元素(这里是 4 index=3)。这是有效的,因为当我们从后面遍历时,元素线性增加直到 3(这是数组第一次开始减少)所以,当我们遇到大于 3 的元素时,它确实是更大的元素或后继元素3 并且 4 左边的所有元素(直到 3)都大于 3 并且 4 右边的所有元素都小于 3。
  4. 交换继任者和支点。
  5. 后缀反转:一旦我们交换了后继者和枢轴,更高的位置值被修改并更新为更大的值,所以必须清楚只有枢轴之后的元素按升序排列才能获得下一个更大的排列.

下面是上述方法的实现:

Java
// Java program to implement
// the next_permutation method
 
import java.util.Arrays;
 
public class nextPermutation {
 
    // Function to swap the data
    // present in the left and right indices
    public static int[] swap(int data[], int left, int right)
    {
 
        // Swap the data
        int temp = data[left];
        data[left] = data[right];
        data[right] = temp;
 
        // Return the updated array
        return data;
    }
 
    // Function to reverse the sub-array
    // starting from left to the right
    // both inclusive
    public static int[] reverse(int data[], int left, int right)
    {
 
        // Reverse the sub-array
        while (left < right) {
            int temp = data[left];
            data[left++] = data[right];
            data[right--] = temp;
        }
 
        // Return the updated array
        return data;
    }
 
    // Function to find the next permutation
    // of the given integer array
    public static boolean findNextPermutation(int data[])
    {
 
        // If the given dataset is empty
        // or contains only one element
        // next_permutation is not possible
        if (data.length <= 1)
            return false;
 
        int last = data.length - 2;
 
        // find the longest non-increasing suffix
        // and find the pivot
        while (last >= 0) {
            if (data[last] < data[last + 1]) {
                break;
            }
            last--;
        }
 
        // If there is no increasing pair
        // there is no higher order permutation
        if (last < 0)
            return false;
 
        int nextGreater = data.length - 1;
 
        // Find the rightmost successor to the pivot
        for (int i = data.length - 1; i > last; i--) {
            if (data[i] > data[last]) {
                nextGreater = i;
                break;
            }
        }
 
        // Swap the successor and the pivot
        data = swap(data, nextGreater, last);
 
        // Reverse the suffix
        data = reverse(data, last + 1, data.length - 1);
 
        // Return true as the next_permutation is done
        return true;
    }
 
    // Driver Code
    public static void main(String args[])
    {
        int data[] = { 1, 2, 3 };
        if (!findNextPermutation(data))
            System.out.println("There is no higher"
                               + " order permutation "
                               + "for the given data.");
        else {
            System.out.println(Arrays.toString(data));
        }
    }
}


输出:
[1, 3, 2]