题目描述
整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。
- 例如,arr = [1,2,3] ,以下这些都可以视作 arr 的排列:[1,2,3]、[1,3,2]、[3,1,2]、[2,3,1] 。
整数数组的 下一个排列 是指其整数的下一个字典序更大的排列。更正式地,如果数组的所有排列根据其字典顺序从小到大排列在一个容器中,那么数组的 下一个排列 就是在这个有序容器中排在它后面的那个排列。如果不存在下一个更大的排列,那么这个数组必须重排为字典序最小的排列(即,其元素按升序排列)。
- 例如,arr = [1,2,3] 的下一个排列是 [1,3,2] 。
- 类似地,arr = [2,3,1] 的下一个排列是 [3,1,2] 。
- 而 arr = [3,2,1] 的下一个排列是 [1,2,3] ,因为 [3,2,1] 不存在一个字典序更大的排列。
给你一个整数数组 nums ,找出 nums 的下一个排列。
必须原地修改,只允许使用额外常数空间。
示例 1:
输入:nums = [1,2,3]
输出:[1,3,2]
示例 2:
输入:nums = [3,2,1]
输出:[1,2,3]
示例 3:
输入:nums = [1,1,5]
输出:[1,5,1]
提示:
- 1 <= nums.length <= 100
- 0 <= nums[i] <= 100
个人解法
Java
class Solution {
public void nextPermutation(int[] nums) {
//34211--41123 43211
//24311--41123 42311 231 312 132 213
int len = nums.length, flag = 0, temp, x = 0;
if (len == 2) {
temp = nums[0];
nums[0] = nums[1];
nums[1] = temp;
} else {
for (int i = len - 1; i > 0; i--) {
if (nums[i] > nums[i - 1]) {
for (int j = len - 1; j > i; j--) {
if (nums[j] > nums[i - 1]) {
temp = nums[j];
nums[j] = nums[i - 1];
nums[i - 1] = temp;
x = 1;
break;
}
}
if (x == 0) {
temp = nums[i];
nums[i] = nums[i - 1];
nums[i - 1] = temp;
}
flag = i;
break;
}
}
//f len 1 2 3 4 5
for (int i = flag + 1; i < len; i++) {
if (nums[flag] > nums[i]) {
temp = nums[i - 1];
nums[i - 1] = nums[flag];
nums[flag] = temp;
break;
}
}
for (int i = flag; i < (len + flag) / 2; i++) {
temp = nums[i];
nums[i] = nums[flag + len - 1 - i];
nums[flag + len - 1 - i] = temp;
}
}
}
}
本质一样的解法,写的短一点,但是速度比较慢,因为调用了包装类自带的方法
public void nextPermutation(int[] nums) {
int len = nums.length, flag = 0, temp, x = 0;
for (int i = len - 1; i > 0; i--) {
if (nums[i] > nums[i - 1]) {
for (int j = len - 1; j > i; j--) {
if (nums[j] > nums[i - 1]) {
temp = nums[j];
nums[j] = nums[i - 1];
nums[i - 1] = temp;
x = 1;
break;
}
}
if (x == 0) {
temp = nums[i];
nums[i] = nums[i - 1];
nums[i - 1] = temp;
}
flag = i;
break;
}
}
Arrays.sort(nums,flag,len);
}
JavaScript
不会
其他解法
JavaScript
看题解后自己的写法
/*
* @lc app=leetcode.cn id=31 lang=javascript
*
* [31] 下一个排列
*/
// @lc code=start
/**
* @param {number[]} nums
* @return {void} Do not return anything, modify nums in-place instead.
*/
var nextPermutation = function (nums) {
if (nums.length <= 1) {
return;
}
const length = nums.length;
let left = length - 2;
let right = length - 1;
while (left >= 0) {
if (nums[left] < nums[right]) {
break;
}
left--;
right--;
}
if (left > -1) {
let k = length - 1;
for (; k > left; k--) {
if (nums[k] > nums[left]) {
break;
}
}
let temp = nums[left];
nums[left] = nums[k];
nums[k] = temp;
nums.splice(right, length - right, ...nums.slice(right).reverse());
} else {
nums = nums.reverse();
}
};
// @lc code=end
他人解法
function nextPermutation(nums) {
let i = nums.length - 2; // 向左遍历,i从倒数第二开始是为了nums[i+1]要存在
while (i >= 0 && nums[i] >= nums[i + 1]) { // 寻找第一个小于右邻居的数
i--;
}
if (i >= 0) { // 这个数在数组中存在,从它身后挑一个数,和它换
let j = nums.length - 1; // 从最后一项,向左遍历
while (j >= 0 && nums[j] <= nums[i]) { // 寻找第一个大于 nums[i] 的数
j--;
}
[nums[i], nums[j]] = [nums[j], nums[i]]; // 两数交换,实现变大
}
// 如果 i = -1,说明是递减排列,如 3 2 1,没有下一排列,直接翻转为最小排列:1 2 3
let l = i + 1;
let r = nums.length - 1;
while (l < r) { // i 右边的数进行翻转,使得变大的幅度小一些
[nums[l], nums[r]] = [nums[r], nums[l]];
l++;
r--;
}
}