字典序下的下乙個排列

2021-08-17 14:41:13 字數 1034 閱讀 2412

一直寫過陣列全排列的演算法,當時接觸的是使用回溯的方法,這樣可以保證生成的全排列一定是按照字典序的,但是今天在做leetcode上的一道題時,問題是要你找到某個排列情況的下乙個按照字典序排列的狀態。

如果直接一點,大可從頭開始做全排列,然後到目標狀態時,在做一次即可找到要的狀態,但是如果題目給的狀態非常靠後,則要花費很大的代價,這樣做就顯得有些笨拙了。

所以做這道題的時候一直在思考如何按照字典序生成全排列。

假設此時給出的狀態時5 2 4 3 1,那麼下乙個狀態要如何確定呢?首先從人的視角來看,絕對會從序列末尾向前開始查詢,例如如果給的狀態時1 2 3 4 5,則很容易發現下乙個狀態應該是1 2 3 5 4,這樣就給出了乙個策略,第一步應該先找從末尾開始向前第一對非逆序數對,這當然有理由,因為如果是逆序的,說明該種情況一定是已經進行過交換了,則絕對不會是下一種情況交換的候選位置,因此會發現5 2 4 3 1中第乙個非逆序數對是2 4,所以交換的候選物件應該是2(2是較小的那乙個);緊接著繼續思考,應該和後面的哪乙個進行交換。首先顯而易見的是,2後面的子串行一定是逆序的。那麼如果要和2交換並且使結果是字典序的下乙個的話,那麼與2交換的一定是2後面的比2大的最小的哪乙個數,因此第二步就是從序列末尾開始向前查詢第乙個比2大的數,與2進行交換(此時為 5 3 4 2 1),那麼下一步也是顯而易見的,3後面的序列應該是由5 3開始的字典序最小的乙個序列,因此要將3後面的序列逆置。最後得到答案5 3 1 2 4。

過程並不複雜,思路和人思考的順序應該是一樣的,直接上coding了。

public void reverse(int nums,int l,int r)

if(i==0)

int index=i-1;

int diff=nums[i-1];

for(i=nums.length-1;i>=0;i--)

int tmp=nums[index];

nums[index]=nums[i];

nums[i]=tmp;

reverse(nums,index+1,nums.length-1);

}

31 下乙個排列 字典序初識

實現獲取下乙個排列的函式,演算法需要將給定數字序列重新排列成字典序中下乙個更大的排列。如果不存在下乙個更大的排列,則將數字重新排列成最小的排列 即公升序排列 必須原地修改,只允許使用額外常數空間。以下是一些例子,輸入位於左側列,其相應輸出位於右側列。1,2,3 1,3,2 3,2,1 1,2,3 1...

31 下乙個排列

public void nextpermutation int nums 從後向前找到第乙個不滿足逆序的元素 int i nums.length 2 for i 0 nums i nums i 1 i 注意,這裡有 可以排除含有重複元素的情況 從i 1位置開始,向後查詢比nums i 大的最小元素 ...

31 下乙個排列

實現獲取下乙個排列的函式,演算法需要將給定數字序列重新排列成字典序中下乙個更大的排列。如果不存在下乙個更大的排列,則將數字重新排列成最小的排列 即公升序排列 必須原地修改,只允許使用額外常數空間。以下是一些例子,輸入位於左側列,其相應輸出位於右側列。1,2,3 1,3,2 3,2,1 1,2,3 1...