Offer 驾到,掘友接招!我正在参与 2022 春招打卡活动,点击查看活动详情。
一、题目描述:
- 下一个排列 —— 难度中等
整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。
例如,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
二、题目和思路分析:
按我最开始的理解,题意是这样的:
如果第一个数字不是数组中最大的数字,后面的排列变动,如果是数组中最大的数字,整个排列变动。
可是我加了几个例子测了一下才发现并不是这样
又看了半天,我渐渐的有点明白了,其实这道题的意思,是把当前的数组合并成一个数字来看,然后要另一种数组的组合,使得这个组合合并的数字刚好比当前数字大。
就是说,将数组转为数字,然后找出数组另一种排列,使得转成的数字刚好比当前数字大。
比如[1,2,3,4]相当于是1234,刚好比它大的应该是1243,也就是[1,2,4,3]
这么想起来,题目不就容易懂了嘛!
再次吐槽:出题人的语文肯定没学好!
明白了题目,下面就是逻辑的构思~
如何快速找出刚好比当前数字大的数字排列呢
答案就是:倒序排列对比!!!
因为当前数字是固定的,所以我们先判断最后两位数字是否能重排为一个更大的数字,如果不可以,我们再判断后n个数字是否能组成更大的数字,这个最大数字必须是刚好比后n个数字更大一点的数字。如果当前数字已经是最大数字,则返回当前数组的正序排列。
// 有了思路,代码搞起来!
三、代码:
代码实现如下:
/**
* @param {number[]} nums
* @return {void} Do not return anything, modify nums in-place instead.
*/
var nextPermutation = function(nums) {
if(nums.length == 1) return nums
let i = nums.length - 1
let arr = []
while(i > -1){
console.log(i)
arr.push(nums[i])
if(nums[i-1] < nums[i]){ // 如果能组成更大的数字
arr.sort((a,b)=>{return a-b})
let j = arr.findIndex(item=>{return item - nums[i-1] > 0})
let a = nums[i-1]
nums[i-1] = arr[j]
arr[j] = a
nums.splice(nums.length - arr.length, arr.length, ...arr)
return nums
}else{ // 如果不能
i--
}
}
if(i < 0){
return nums.sort((a,b)=>{return a-b})
}
}
四、总结:
这道题其实不难,但是想思路和写代码都花了不少时间,效率不够高,我什么时候才能更高更快更强?
加油吧!