【Next Permutation】cpp

題目算法

Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers.spa

If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending order).code

The replacement must be in-place, do not allocate extra memory.blog

Here are some examples. Inputs are in the left-hand column and its corresponding outputs are in the right-hand column.
1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1ip

代碼element

class Solution {
public:
    void nextPermutation(vector<int> &num) {
        const int len = num.size();
        if (len<2) return;
        std::vector<int>::iterator pivot=num.end();
        // find the pivot pointer
        for (std::vector<int>::iterator i = num.end()-1; i != num.begin(); --i)
        {
            if ( *i>*(i-1) )
            {
                pivot = i-1;
                break;
            }
        }
        // if the largest, directly reverse
        if ( pivot==num.end() ) 
        {
            std::reverse(num.begin(), num.end());
            return;
        }
        // else exchange the value of pivot and it's next larger element
        std::vector<int>::iterator next_larger_pivot = pivot;
        for (std::vector<int>::iterator i = num.end()-1; i != num.begin(); --i)
        {
            if ( *pivot<*i )
            {
                next_larger_pivot = i;
                break;
            }
        }
        std::swap(*pivot, *next_larger_pivot);
        // reverse the pivot's right elements
        std::reverse(pivot+1, num.end());
    }
}

Tips:it

上網搜搜Next Permutation的算法,分四步:io

1. 從右往左 找左比右小的左 記爲pivotclass

2. 從右往左 找第一個比pivot大的 記爲next_larger_pivotcoding

3. 交換pivot與next_larger_pivot所指向的元素

4. 讓pivot右邊的元素(不包括pivot)逆序

按照上面的算法,多測測case,找找邊界條件。

注意找到pivot和next_larger_pivot以後要break退出循環。

===================================

第二次過這道題,思路已經記得比較模糊了。能作到的就是撿一遍思路,coding的過程很快。

            // from right to left find first violate increase trend
            int pos1 = -1;
            for ( int i=nums.size()-1; i>0; --i )
            {
                if ( nums[i]>nums[i-1] )
                {
                    pos1 = i-1;
                    break;
                }
            }
            // cout << "pos1:" << pos1 << endl;
            if ( pos1==-1 ) 
            {
                std::reverse(nums.begin(), nums.end());
                return;
            }
            // from right to left find the first larger than pos1
            int pos2 = nums.size()-1;
            for ( int i=nums.size()-1; i>=0; --i )
            {
                if ( nums[i]>nums[pos1] )
                {
                    pos2 = i;
                    break;
                }
            }
            // cout << "pos2:" << pos2 << endl;
            // swap pos1 pos2
            std::swap(nums[pos1], nums[pos2]);
            // reverse from pos1's right to end
            std::reverse(nums.begin()+pos1+1, nums.end());

這個算法就是個套路,多掃幾遍記住就OK了。

相關文章
相關標籤/搜索