LeetCode32——next permutation

这是一道关于数组排列的题目,题面如下:
在这里插入图片描述

事实上,熟悉C++ STL的朋友一看到这道题,应该就联想到这是STL中已经提供的的一个泛型算法。在STL中的算法功能和此题描述的完全一致,只不过在STL中返回值是bool类型,如果存在下一个更大的排列,那么就返回true,并将容器修改为下一个更大的排列。C++ Primer 5th edition中附录解释如下:
在这里插入图片描述
所以其实这道题的AC代码就是…

// using STL generic algorithm directly, hahaha... 
next_permutation(nums.begin(), nums.end());

亲测,这样真的是可以通过的:)
好了,下面说说这道题的解法,首先我按顺序列出123这三个数字的组合,从上到下为应该返回的顺序:

123
132
213
231
312
321

不得不说这道题还是有些难度的,很难去解释背后的原理或者奥秘。这次就当一个树洞,把算法流程大致描述出来,一方面算是加深了对STL中算法的实现的理解,也以备以后回顾,以下end表示最后一个元素的索引:

1.令i从后向前遍历序列,找到第一个满足nums[i] < nums[i+1]的元素下标i,同时可以推知[i+1,end]都是降序序列。如果i<0,表示当前序列完全降序,已经达到最大字典序,直接转到4,否则执行2,3,4。
2.令j再次从后向前遍历序列,找到第一个满足nums[i] < nums[j]的元素下标j。
3.交换元素nums[i]和nums[j]。
4.将序列的[i+1, end]部分完全逆置。

这个算法的思想就是尽可能保证找到的交换数对(nums[i], nums[j])是数值上最接近的最靠近结尾的,在交换完成之后通过逆置交换点之后的数据来保证序列的升序,升序是最逼近下一个字典序排列的情况。

完整的代码如下:

class Solution {
    
    
    /*swap the two elements in vector, i & j are index*/
    void swap(vector<int>&nums, int i, int j)
    {
    
       
        if(i == j)
            return;

        /*intermediate variable*/ 
        int Temp;
        Temp = nums[i], nums[i] = nums[j], nums[j] = Temp;
    }

    /*reverse the whole vector to get the min permutation*/
    void reverse(vector<int>& nums, int h, int t)
    {
    
    
        int Head = h, Tail = t;
        while(Head <= Tail)
            swap(nums, Head++, Tail--);
    }

public:
    void nextPermutation(vector<int>& nums) {
    
    
        // using STL generic algorithm directly, hahaha... 
        // next_permutation(nums.begin(), nums.end());
        if(nums.size() == 1)
            return;

        int Tail = nums.size() - 2, SearchBigger = nums.size() - 1;
        /*find the element's index Tail which satisfies nums[i] < nums[i + 1]*/
        /*Tail is as big as possible*/
        while(Tail >= 0 && nums[Tail] >= nums[Tail + 1] )
            --Tail;
        
        /*if the element can be found, then search the closest bigger element*/
        if(Tail >= 0)
        {
    
    
            while(SearchBigger > Tail && nums[SearchBigger] <= nums[Tail])
                --SearchBigger;
            swap(nums, SearchBigger, Tail);
        }
        
        /*reverse the array[Tail+1, End] to get ready for next permutation*/
        reverse(nums, Tail + 1, nums.size() - 1);
    }
};

此算法仍需反复斟酌

Guess you like

Origin blog.csdn.net/zzy980511/article/details/115540381