首页 > 试题广场 >

下一个排列

[编程题]下一个排列
  • 热度指数:2070 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
给定一个数组,将数组重新排列,得到一系列数组排列S,请你从S中,找出恰好比当前数组排列字典序大于1的数组排列。
1.[1,2,3]的得到的数组排列S有:[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]。
2.该题数组排列的字典序大小排序规则:2个数组排列的元素按顺序比较,直到数组元素不相等为止,不相等的第一个元素,谁的元素大,谁的字典序比较大,比如数组a=[1,2,3]与数组b=[1,3,2]比较:a[0]=b[0],a[1]<b[1],此时出现了第一个不相同的,且a[1]<b[1],则a的字典序小于b的字典序。且[1,3,2]的字典序在排列S中,正好在[1,2,3]的后面,视为[1,3,2]的字典序比[1,2,3]的字典序大于1。
3.如果不存在更大的数组排列,则返回最小的数组排列。

数据范围:排列长度满足 ,排列中的值满足
示例1

输入

[1,2,3]

输出

[1,3,2]
示例2

输入

[3,2,1]

输出

[1,2,3]

说明

[3,2,1]是当前最大的数组排列了,不存在比它更大的了,故返回最小的数组排列      
示例3

输入

[2]

输出

[2]
从右往左,先找到第一个非降序元素,再找到第一个比它大的元素,两者交换即可,
如果未找到,说明数组排序是以最大值的形式,直接翻转数组即可,代码右注释说明:
public int[] nextPermutation(int[] nums) {
        int n = nums.length;
        int i = n - 2;

        // 从右到左找到第一个不满足降序的相邻元素对
        while (i >= 0 && nums[i] >= nums[i + 1]) {
            i--;
        }
        // 示例: 98765556789
        // i = 3 nums[i] = 6
        if (i >= 0) {
            int j = n - 1;
            // 从右到左找到第一个大于nums[i]的元素, 即 j = 8 nums[j] = 7
            while (j >= 0 && nums[j] <= nums[i]) {
                j--;
            }
            // 交换nums[i]和nums[j] , 即 98765556789 -> 98775556689
            swap(nums, i, j);
        }

        // 将nums[i+1]到nums[n-1]的元素反转
        reverse(nums, i + 1, n - 1);

        return nums;
    }

    // 交换两个元素
    private void swap(int[] nums, int i, int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }

    // 翻转数据,写法比递归效率高
    private void reverse(int[] nums, int start, int end) {
        while (start < end) {
            swap(nums, start, end);
            start++;
            end--;
        }
    }


发表于 2024-04-25 13:41:31 回复(0)
import java.util.*;

public class Solution {

    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param nums int整型一维数组 
     * @return int整型一维数组
     */

    public int[] nextPermutation (int[] nums) {
        int n = nums.length;
        int i = n - 2, j = n - 1;
        while (i >= 0 && nums[i] >= nums[i+1]) -- i;
        if (i >= 0){
            while (j > i && nums[i] >= nums[j]) -- j;
            // 交换数组中这2个位置的值
            getSwap(nums, i ,j);
        }
        // 翻转,从某个位置之后的部分数组
        getReverse(nums, i+1);
        return nums;
    }

    private void getReverse(int[] nums, int i) {
        int left = i, right = nums.length - 1;
        while (left < right){
            getSwap(nums, left ++, right --);
        }
    }

    private void getSwap(int[] nums, int i, int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
}

发表于 2021-12-22 14:56:56 回复(0)
import java.util.*;
public class Solution {
    ArrayList<ArrayList<Integer>> res=new ArrayList<>();
    boolean[] mark;
    public ArrayList<ArrayList<Integer>> permuteUnique(int[] num) {
        mark = new boolean[num.length];
        Arrays.sort(num);
        LinkedList<Integer> path = new LinkedList<Integer>();
        dfs(num,path);
        return res;
    }
    public void dfs(int[] num,LinkedList<Integer> path){
        if(path.size()==num.length){
            if(res.contains(path)) return;
            res.add(new ArrayList(path));
                return;
        }
        for(int i=0;i<num.length;i++){
            if(mark[i]==true)
                continue;
            path.add(num[i]);
            mark[i]=true;
            dfs(num,path);
            path.remove(path.size()-1);
            mark[i]=false;
        }
    }
    public int[] nextPermutation (int[] nums) {
        if(nums.length==1) return new int[]{nums[0]};
        int[] cur=new int[nums.length];
        for(int i=0;i<nums.length;i++){
            cur[i]=nums[i];
        }
        ArrayList<ArrayList<Integer>> res = permuteUnique(cur);
        int mark=0;int n=res.get(0).size();
        for(int i=0;i<res.size();i++){
            ArrayList a=res.get(i);
            for(int j=0;j<n;j++){
                if((Integer)a.get(j)==nums[j]){
                    if(j==n-1)
                        mark=i;
                    continue;}
                else break;
            }
        }
        if(mark==res.size()-1){
            mark=-1;
        }
        int[] ans=new int[n];int cout=0;
        for(int i:res.get(mark+1)){
            ans[cout++]=i;
        }
        return ans;
    }
}
我肯定是对的,只不过超时了,终究还是太菜,谁写出来了踢我一脚

发表于 2021-11-17 18:30:33 回复(1)