下一个排列

题目描述:实现获取 下一个排列 的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。

如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。

必须 原地 修改,只允许使用额外常数空间。

示例说明请见LeetCode官网。

来源:力扣(LeetCode)

链接:https://leetcode-cn.com/problems/next-permutation/

著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解法一:遍历数组

首先,如果数组为空或者数组只有一个元素,直接返回;

声明一个变量handled表示是否找到更大的排列,默认是false,left和right分别记录找到更大排列需要调换的数字,然后双重循环遍历数组判断是否存在更大的排列,具体遍历过程如下:

  • 从数组的最后一位开始遍历,如果存在前面的数字比当前数字大的,则left和right分别记录当前索引位,并将handled更新为true,然后遍历下一位;
  • 遍历过程中需要判断如果找到一种符合条件的数字,要判断是否比之前已得到的情况更优,如果是,更新left和right。

然后根据handled判断,如果为false,说明没有更大的排列,也就是不存在下一个更大排列,将数字重新排列成最小的排列,就是将顺序倒排;如果为true,则需要进行如下处理:

  • 首先,将left和right位置的数字调换位置;
  • 然后将 right+1 后面的数字倒排,这一步是为了将后面的数字排列成最小的值;
  • 然后将 left+1到right-1 之间的数字跟 right+1到nums.length-1 的数字整体调换顺序,这一步也是为了将left后面的数字排列成最小的值;
  • 然后将 left+1 位置的数字移到小于它的数字之后,这一步是为了获取最终的排列结果。
import java.util.Arrays;

public class LeetCode_031 {
public static void nextPermutation(int[] nums) {
// 如果数组为空,或者数组的长度为0或者只有一个元素,不用处理
if (nums == null || nums.length < 2) {
return;
}
// 是否找到更大的排列
boolean handled = false;
// 首先找到需要调换位置的数字
int left = -1, right = -1;
for (int i = nums.length - 1; i > 0; i--) {
for (int j = i - 1; j >= 0; j--) {
if (nums[i] > nums[j]) {
if (j > left) {
left = j;
right = i;
} else if (j == left) {
if (i == right) {
left = j;
right = i;
}
}
handled = true;
break;
}
}
} if (handled) {
// 找到更大的排列
// 1.将 right 的数字和 left 的数字调换位置
exch(nums, left, right);
// 2.首先将 right+1 后面的数字倒排
for (int x = right + 1; x < (nums.length + right + 1) / 2; x++) {
exch(nums, x, nums.length - 1 - (x - right) / 2);
}
// 3.然后将 left+1到right-1 之间的数字跟 right+1到nums.length-1 的数字整体调换顺序
for (int x = right - 1; x >= left + 1; x--) {
for (int y = x; y < nums.length - 1; y++) {
exch(nums, y, y + 1);
}
}
// 4.然后将 left+1 位置的数字移到小于它的数字之后
for (int x = left + 1; x < nums.length - 1; x++) {
if (nums[x] > nums[x + 1]) {
exch(nums, x, x + 1);
} else {
break;
}
}
} else {
// 如果handled为false,说明没有更大的排列,也就是不存在下一个更大排列,将数字重新排列成最小的排列,
// 就是将顺序倒排
for (int i = 0; i < nums.length / 2; i++) {
exch(nums, i, nums.length - 1 - i);
}
}
} private static void exch(int[] nums, int left, int right) {
int temp = nums[right];
nums[right] = nums[left];
nums[left] = temp;
} public static void main(String[] args) {
int[] nums = new int[]{4, 2, 0, 2, 3, 2, 0};
System.out.println("=====处理前=====");
Arrays.stream(nums).forEach(num -> {
System.out.print(num + " ");
});
System.out.println();
System.out.println("=====处理后=====");
nextPermutation(nums);
Arrays.stream(nums).forEach(num -> {
System.out.print(num + " ");
});
}
}

【每日寄语】 努力是人生应有的态度,睁开眼就是新的开始。

LeetCode-031-下一个排列的更多相关文章

  1. LeetCode:下一个排列【31】

    LeetCode:下一个排列[31] 题目描述 实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列. 如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排 ...

  2. 【LeetCode】下一个排列【找规律】

    实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列. 如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列). 必须原地修改,只允许使用额外常数空间. ...

  3. Java实现 LeetCode 31下一个排列

    31. 下一个排列 实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列. 如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列). 必须原地修改,只允许 ...

  4. LeetCode 31. 下一个排列(Next Permutation)

    题目描述 实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列. 如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列). 必须原地修改,只允许使用额外常 ...

  5. leetcode 31下一个排列

    /** 验证一般情况(元素数目大于等于3)有几个情况分析:两个特殊情况: 6 5 4 3 2 1 完全反序,这种序列没有下一个排序,因此重新排序1 2 3 4 5 6 1 2 3 4 5 6 完全升序 ...

  6. LeetCode 31. 下一个排列 | Python

    31. 下一个排列 题目 实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列. 如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列). 必须原地修改, ...

  7. [LeetCode] Next Permutation 下一个排列

    Implement next permutation, which rearranges numbers into the lexicographically next greater permuta ...

  8. 031 Next Permutation 下一个排列

    实现获取下一个排列函数,这个算法需要将数字重新排列成字典序中数字更大的排列.如果不存在更大的排列,则重新将数字排列成最小的排列(即升序排列).修改必须是原地的,不开辟额外的内存空间.这是一些例子,输入 ...

  9. [LeetCode] 31. Next Permutation 下一个排列

    Implement next permutation, which rearranges numbers into the lexicographically next greater permuta ...

  10. 31,Leetcode下一个排列 - C++ 原地算法

    题目描述 实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列. 如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列). 必须原地修改,只允许使用额外常 ...

随机推荐

  1. SpringBoot+Minio搭建不再爆肝秃头的分布式文件服务器

    前言 1).有人一定会问,为什么不用FastDFS?众所周知,FastDFS的原生安装非常复杂,有过安装经验的人大体都明白,虽然可以利用别人做好的docker直接安装,但真正使用过程中也可能出现许多莫 ...

  2. APschedule定时任务

    APScheduler是Python的一个定时任务框架,可以很方便的满足用户定时执行或者周期执行任务的需求, 它提供了基于日期date.固定时间间隔interval .以及类似于Linux上的定时任务 ...

  3. Atcoder ARC-068

    A 不难发现从 \(5\) 开始一直往 \(6\) 转再转回来是最优的,直接模拟即可. B 不难发现可以将多余部分直接贪心消去,最后必然会剩下两个或 \(1\) 个多余的数. 如果剩下两个,此时多余的 ...

  4. c语言数据结构,你可能还不知道的顺序表

    数据结构顺序表 顺序表定义 1,前言 线性表的顺序存储又称为顺序表.它是用一组地址连续的存储单元依次存储线性表中的数据元素,从而使得逻辑上相邻的两个元素在物理位置上也相邻.其最大的特点就是:元素的逻辑 ...

  5. Spring IOC-基于XML配置的容器

    Spring IOC-基于XML配置的容器 我们先分析一下AbstractXmlApplicationContext这个容器的加载过程. AbstractXmlApplicationContext的老 ...

  6. Linux性能优化实战(二)

    一.CPU使用率过高 1,CPU使用率 a>节拍率 为了维护CPU时间,Linux通过事先定义的节拍率(内核中表示为HZ),触发时间中断,并使用全局变量Jiffies记录开机以来的节拍数.每发生 ...

  7. Redis 源码简洁剖析 12 - 一条命令的处理过程

    命令的处理过程 Redis server 和一个客户端建立连接后,会在事件驱动框架中注册可读事件--客户端的命令请求.命令处理对应 4 个阶段: 命令读取:对应 readQueryFromClient ...

  8. Solution -「JOISC 2021」「LOJ #3491」道路建设

    \(\mathcal{Description}\)   Link.   平面上有 \(n\) 个互不重合的点 \((x_{1..n},y_{1..n})\),求其两两曼哈顿距离的前 \(m\) 小值. ...

  9. 【摸鱼神器】基于SSM风格的Java源代码生成器 单表生成 一对一、一对多、多对多连接查询生成

    一.序言 UCode Cms 是一款Maven版的Java源代码生成器,是快速构建项目的利器.代码生成器模块属于可拆卸模块,即按需引入.代码生成器生成SSM(Spring.SpringBoot.Myb ...

  10. tomcat 上传文件权限不足

    参考:https://www.cnblogs.com/houchaoying/p/8652040.html tomcat-bin-catalina.sh UMASK="0027" ...