解法一:
/**
* @param {number[]} nums
* @return {void} Do not return anything, modify nums in-place instead.
*/
var nextPermutation = function(nums) {
let right = nums.length -1
let left = right-1
let flag = true //用来控制循环的,只要数组发生了一次变化就立刻出循环
let k = nums.length-1
while(flag){
if(left < 0){
right = right-1 < 0 ? 0 : right-1
left = right -1 < 0 ? 0 :right-1 //left设置为right左边的数字,很容易变成-1,就跳到最后一个了,所以如果变成负的,就手动置零
}else {
if(nums[left] < nums[right] ){ //判断相邻两个数是否有拐点出现
for(; k > right ; k-- ){ //for循环找到除了拐点以外,比right的值要小的最大值,但是又不能比left的元素的值小
if(nums[k] < nums[right] && nums[k] > nums[left])
right = k
}
[nums[left],nums[right]] = [nums[right],nums[left]] // 这两个元素对换
let arr = nums.splice(left+1,nums.length-left-1)
arr.sort((a,b) => a-b) // left右边的值升序排列
nums.push(...arr) // 数组合并
flag = false
}else{
left --
right --
}}
if(right == 0 && flag === true){ //数组到头了都没有拐点,说明是逆序排列的,直接数组反转
nums.reverse()
flag = false
}
}
}
执行用时: 68 ms
内存消耗: 42.1 MB
主要思路:
- 要求输出的值要比上一次的大那么一点,但是只大一点点,所以就要在数字的尾部进行改动,让数组进行最小的增加,所以循环都是从尾部开始
- 要想进行最小的变化,就要把尾部的大的值往前和前面的小的值进行交换。
- 找到拐点,就是说,从后往前看,数字在变大,但有了一个比前一个小的值,算作拐点,例如:132 ,13就算做一个拐点,拐点左边是要交换到后面的小值(1),拐点右边是要放到前面的大的值(3),但是这样交换,不可以保证是最小的增加,例如312(13交换),但实际更小的增加是213(21交换)
- 所以在找到拐点之后,通过一个for循环从尾部开始找到,比拐点大的值小,但是又比拐点小的值大的数字,和拐点左边的值进行交换,所以有一个for循环,他从尾部开始循环,到right(right就是拐点右边的值的下标)的右边就结束。
- 找到之后,交换拐点左边的值(nums[left])和刚刚找到的偏小的大的值,可以在这里用解构赋值的语法交换
- 然后right右边的值升序排列,就会是最小值,所以把后面那一部分用splice提出来,排完序,再合回去。
- 如果一直循环到头都没有这个拐点,说明是降序排列,直接数组翻转
解法二(sort换成reverse):
/**
* @param {number[]} nums
* @return {void} Do not return anything, modify nums in-place instead.
*/
var nextPermutation = function(nums) {
let right = nums.length -1
let left = right-1
let flag = true
let k=nums.length-1
while(flag){
if(left < 0){
right = right-1 < 0 ? 0 : right-1
left = right -1 < 0 ? 0 :right-1
}else {
if(nums[left] < nums[right] ){
for(; k > right;k-- ){
if(nums[k] > nums[left] && nums[k]<= nums[right])
right = k
}
[nums[left],nums[right]] = [nums[right],nums[left]]
let arr = nums.splice(left+1,nums.length-left-1)
arr.reverse()
nums.push(...arr)
flag = false
}else{
left --
right --
}}
if(right == 0 && flag === true){
nums.reverse()
flag = false
}
}
}
执行用时: 84 ms
内存消耗: 41.7 MB