Next Permutation

carlblack

每日算法——leetcode系列


问题 Next Permutation

Difficulty: Medium

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

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

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

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,1

class Solution {
public:
    void nextPermutation(vector<int>& nums) {
        
    }
};

翻译

下一个排列

难度系数:中等
实现下一个排列,此排列是按字典的顺序的来重新编排数字得到的下一个大的数字排列。
如果不能重排成下一个大的数字排列,那必须按最小可能的顺序来重排(例如:按升序排列)
重排必须在原地,不准分配额外的内存。

思路

此题的意思就是按字典的顺序从当前的顺序找下一个顺序的排列组合,什么是字典顺序,基本规则就是字母表从小到大, 如果一些单词是abcd组成,字母表顺序是abcd->abdc->acbd->acdb->adbc->adcb->...依次往下。

分析规律:

  • abcd->abdc 最后两个交换

  • abdc->acbd 先bc交换,再db交换

  • acbd->acdb bd交换

  • acdb->adbc 先cd交换, 再cb交换

  • adbc->adcb 最后两个交换
    规律有点难发现,其实在交换中我们下意识运用了规律(我是偷了别个的思想)。

以abcd->abdc为例

  1. 从右到左看,先找到第一个打破升序规律的字母c

  2. 再从头来从右到左,找出c右边比c大的字母d(其实字典顺序他肯定在c右边),并把c右边的字母作为一个分区段

  3. 交换c,d

  4. 分区段的字母再按升序排列,这里由于就剩下c,升序排序后还是剩下c

代码

class Solution {
public:
    void nextPermutation(vector<int>& nums) {
        size_t len = nums.size();
        if (len == 1 || len == 0){
            return;
        }
        int firstBreakNum = -1;
        size_t firstBreakIndex = -1;
        for (size_t i = len ;i > 1; --i){
            if (nums[i-1] > nums[i-2]){
                firstBreakNum = nums[i-2];
                firstBreakIndex = i - 2;
                break;
            }
        }
        // 没找到打破升序规律的,那就全部升序排列
        if (firstBreakNum == -1){
            reverse(nums.begin(), nums.end());
            return;
        }
        for (size_t i = len; i > 1; --i){
            if (nums[i-1] > firstBreakNum){
                swap(nums[i-1], nums[firstBreakIndex]);
                break;
            }
        }
        auto iter = nums.begin();
        for (size_t i = 0; i < firstBreakIndex + 1; ++i){
            iter++;
        }
        reverse(iter, nums.end());
    }
};
阅读 5.2k

每日算法
脑子不好使,得吃药, 记录的习惯是最好的药引子。
4 声望
16 粉丝
0 条评论
4 声望
16 粉丝
文章目录
宣传栏