LeetCode 第31題 下一個排列


(一)題目描述

  實現獲取下一個排列的函數,算法需要將給定數字序列重新排列成字典序中下一個更大的排列。

  如果不存在下一個更大的排列,則將數字重新排列成最小的排列(即升序排列)。

  必須原地修改,只允許使用額外常數空間。

  以下是一些例子,輸入位於左側列,其相應輸出位於右側列。
  1,2,3 → 1,3,2
  3,2,1 → 1,2,3
  1,1,5 → 1,5,1

 

  


 

(二)算法思路

  首先解釋一下什么是字典序:

  設P是1~n的一個全排列:p=p1p2......pn=p1p2......pj-1pjpj+1......pk-1pkpk+1......pn
  1)從排列的右端開始,找出第一個比右邊數字小的數字的序號j(j從左端開始計算),即 j=max{i|pi<pi+1}
  2)在pj的右邊的數字中,找出所有比pj大的數中最小的數字pk,即 k=max{i|pi>pj}(右邊的數從右至左是遞增的,因此k是所有大於pj的數字中序號最大者)
  3)對換pj,pk
  4)再將pj+1......pk-1pkpk+1......pn倒轉得到排列p'=p1p2.....pj-1pjpn.....pk+1pkpk-1.....pj+1,這就是排列p的下一個排列。
 
   解法:
  解法一:我們可以把所有的排序全部列出來,然后找到下一排列,但是這樣的算法效率太低,LeetCode肯定不能通過.但是這也是最簡單和最容易想到的方法了.
 
  解法二:一遍掃描法
  1. 我們直接從后往前掃描,先把最后一位當做基准,
  2. 看倒數第二位比倒數第一位大還是小,如果比倒數第一位大,呢就把倒數二位當做基准,直到找到比它小的一位數,我們將其記為 a.
  3. 然后用這位數去和它之后的數進行比較,找到比它大的數中最小的一位b.
  4. 然后交換a和b的位置
  5. 再將a之后的數字逆序排列,就是最終的結果.

   我覺得自己已經解釋的很清楚了,但是為了大家更好的去理解這個過程,下面請看一張動圖,就能更加清晰的掌握這個過程了.(圖是借鑒領扣的)

  Next Permutation


 

(三)LeetCode   AC代碼

  

 1 public class Solution {
 2     public void nextPermutation(int[] nums) {
 3         int i = nums.length - 2;
 4         while (i >= 0 && nums[i + 1] <= nums[i]) {
 5             i--;
 6         }
 7         if (i >= 0) {
 8             int j = nums.length - 1;
 9             while (j >= 0 && nums[j] <= nums[i]) {
10                 j--;
11             }
12             swap(nums, i, j);
13         }
14         reverse(nums, i + 1);
15     }
16 
17     private void reverse(int[] nums, int start) {
18         int i = start, j = nums.length - 1;
19         while (i < j) {
20             swap(nums, i, j);
21             i++;
22             j--;
23         }
24     }
25 
26     private void swap(int[] nums, int i, int j) {
27         int temp = nums[i];
28         nums[i] = nums[j];
29         nums[j] = temp;
30     }
31 }

 

 

 雖然不是很難,但是自己還是搞了很久.

   自己將其總結下來,相信慢慢的自己會有思路去寫算法.


 

 

     

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM