Next Permutation LC解題記錄

題目內容

給出一個數組,從新排列,返回『下一個排列,題目的描述中還給出了幾個例子。數組

解決思路

有一首歌名是下一個天亮,不過和這道題沒什麼關係。還有一類題是已有一堆數字要返回全部的排列方式,和這道題也沒什麼關係。按照題目的描述中的例子,好比:
[1,2,3] -> [1,3,2] 觀察了一下,是交換了2和3的位置。
[3,2,1] -> [1,2,3]這個就是整個數組的逆序排列。
根據這兩個例子猜想,須要兩個輔助的方法,一個是交換(swap),另外一個是逆序(reverse)。
繼續看,交換的地方應該是相鄰兩個數字後一個比前一個大的狀況,並且靠後的優先,好比[#$%,1,2,3]返回的也是[#$%,1,3,2]。因此第一步的思路就是從後往前找,找一對兒符合要求的相鄰數字。若是找到頭都沒找到,那能夠直接逆序輸出返回結果了。
找到這對兒以後,小的數字確定要交換到後面的,先設定這個小數字的位置是first。而後要交換的數字是first後面比它大的裏面最小的,就是貼着頭皮理髮的感受。交換過來以後,再把first後面的部分逆序輸出就行了。
這道題的關鍵在於,找到規律,數學上的規律。關鍵的關鍵在於,找不到規律就看discussion吧。code

code

public class Solution {
    public void nextPermutation(int[] nums) {
        //排除corner case
        if(nums == null || nums.length < 2) return;
        //找那對兒數字
        int right = nums.length-1;
        while(right > 0){
            if(nums[right-1] < nums[right]){
                break;
            }
            right--;
        }
        //沒找着符合要求的狀況,直接reverse。
        if(right == 0){
            reverse(nums, 0, nums.length-1);
            return;
        }
        
        int first = right-1;
        int nextBig = right;
        while(right < nums.length){
            //要大,還不能太大。
            if(nums[right] <= nums[nextBig] && nums[right] > nums[first]){
                nextBig = right;
            }
            right++;
        }
        swap(nums, first, nextBig);
        reverse(nums, first+1, nums.length-1);
    }
    
    private void swap(int[] nums, int first, int second){
        int temp = nums[first];
        nums[first] = nums[second];
        nums[second] = temp;
        return;
    }
    private void reverse(int[] nums,int start, int end){
        while(start < end){
            int temp = nums[start];
            nums[start] = nums[end];
            nums[end] = temp;
            start++;
            end--;
        }
    }
}

複雜度分析

這個很顯然是O(n)了,第一遍找一對兒數字的時候掃了一遍,而後第二次再找nextBig的時候又掃了一遍,最後逆序輸出,掃了好幾回,最後依然是O(n)。leetcode

相關文章
相關標籤/搜索