数组的合并和升序排列_leetcode No.31 下一个排列
題目鏈接:
下一個排列 - 力扣(LeetCode)?leetcode-cn.com題目描述:
實(shí)現(xiàn)獲取下一個排列的函數(shù),算法需要將給定數(shù)字序列重新排列成字典序中下一個更大的排列。
如果不存在下一個更大的排列,則將數(shù)字重新排列成最小的排列(即升序排列)。
必須原地修改,只允許使用額外常數(shù)空間。
以下是一些例子,輸入位于左側(cè)列,其相應(yīng)輸出位于右側(cè)列。1,2,3 → 1,3,23,2,1 → 1,2,31,1,5 → 1,5,1
解題思路:
最直接的想法是暴力法,找出由給定數(shù)組的元素形成的列表的每個可能的排列,并找出比給定的排列更大的排列。但是時間復(fù)雜度是
,因?yàn)榭赡艿呐帕锌傆嬘? 個,爆表了都,我們得想想有沒有更快的算法。首先,如果是一個降序數(shù)組,沒有可能有下一個更大的排列,直接反轉(zhuǎn)變成升序數(shù)組就好。
然后,我們再來看看一般情形,假設(shè)數(shù)組名為
,長度為 ,這個數(shù)組中必然存在著 ,使得 ,我們對 以及其右邊的數(shù)進(jìn)行重新排列就可以得到一個比初始排列大的排列。而要想找到下一個排列,我們可以從右往左來找到第一對滿足
的 。接著,我們需要在 的右邊發(fā)現(xiàn)一個 ,使得 ,且 在所有大于 的值中最小,我們交換 和 的位置。來自 leetcode 官方題解現(xiàn)在在索引
處有正確的數(shù)字。但目前的排列仍然不是答案,我們需要通過僅使用 右邊的數(shù)字來形成最小的排列。 因此,我們需要放置那些按升序排列的數(shù)字,以獲得最小的排列。可能你想到直接排序就好了嘛,但其實(shí)還有更簡單的方法。因?yàn)樵趶挠覀?cè)掃描數(shù)字時,我們只是持續(xù)遞減索引直到我們找到
和 這對數(shù)。其中, 。 右邊的所有數(shù)字都已按降序排序。此外,交換 和 也并未改變該順序。因此,我們只需要反轉(zhuǎn) 之后的數(shù)字,就可以獲得下一個最小的字典排列。代碼如下:
class Solution { public:void nextPermutation(vector<int>& nums) {int n = nums.size(), k, l;for (k = n - 2; k >= 0; k--) {if (nums[k] < nums[k + 1]) {break;}}if(k < 0) {reverse(nums.begin(), nums.end());}else {for (l = n - 1; l > k; l--) {if (nums[l] > nums[k]) {break;}}swap(nums[k], nums[l]);reverse(nums.begin()+k+1, nums.end());}} };其實(shí) C++ 里面有庫函數(shù) next_permutation 可以直接幫我們獲取下一個排列。。。
如果有任何疑問,歡迎提出。如果有更好的解法,也歡迎告知。
總結(jié)
以上是生活随笔為你收集整理的数组的合并和升序排列_leetcode No.31 下一个排列的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 飞机大战(Java)
- 下一篇: java 正则表达式验证邮箱格式是否合规