HOT99-下一个排列

        leetcode原题链接:下一个排列

题目描述

      整数数组的一个 排列  就是将其所有成员以序列或线性顺序排列。

  • 例如,arr = [1,2,3] ,以下这些都可以视作 arr 的排列:[1,2,3][1,3,2][3,1,2][2,3,1] 。
  • 整数数组的 下一个排列 是指其整数的下一个字典序更大的排列。更正式地,如果数组的所有排列根据其字典顺序从小到大排列在一个容器中,那么数组的 下一个排列 就是在这个有序容器中排在它后面的那个排列。如果不存在下一个更大的排列,那么这个数组必须重排为字典序最小的排列(即,其元素按升序排列)。
  • 例如,arr = [1,2,3] 的下一个排列是 [1,3,2] 。
  • 类似地,arr = [2,3,1] 的下一个排列是 [3,1,2] 。
  • 而 arr = [3,2,1] 的下一个排列是 [1,2,3] ,因为 [3,2,1] 不存在一个字典序更大的排列。

      给你一个整数数组 nums ,找出 nums 的下一个排列。

      必须 原地 修改,只允许使用额外常数空间。

示例 1:

输入:nums = [1,2,3]
输出:[1,3,2]

示例 2:

输入:nums = [3,2,1]
输出:[1,2,3]

示例 3:

输入:nums = [1,1,5]
输出:[1,5,1]

提示:

  • 1 <= nums.length <= 100
  • 0 <= nums[i] <= 100

解题方法

    1. 从右边向左,寻找第一个降序的数字j,对应的波峰为i (j=i-1)。

    2. 再从右向左,找到第一个比j大的元素位置k(这个k必然存在,因为nums[j]>nums[i])。

    3. 交换nums[j]和nums[k]。

    4. 对[j+1, n-1]区间的元素从小到大排序,此时只需要反转下数字即可reverse。

C++代码

#include 
#include 
#include  // std::reverse()

class Solution {
public:
    void nextPermutation(std::vector& nums) {
        int n = nums.size();
        if (n == 0) {
            return;
        }
        // 1.从右边向左,寻找第一个将序的数字j,对应的波峰为i
        int i = n - 1; //从右向左寻找第一个波峰的位置
        while (i > 0 && nums[i] <= nums[i - 1]) { //比较num[i]和num[i-1]的值,所以这里
            i--;
        }
        if (i == 0) { //i到了最左边,说nums[0]是最大值,此时没有更大的值,则返回最小值(因为数组本身已经是最大值)
            std::reverse(nums.begin(), nums.end());
            return;
        }
        int j = i - 1; //j指向第一个波峰左边的位置
        // 2.再从右向左,找到第一个比j大的元素位置k(这个k必然存在,因为nums[j]>nums[i])
        int k = n - 1;
        while (k >= i && nums[k] <= nums[j]) {
            k--;
        }
        // 3. 交换nums[j]和nums[k]
        std::swap(nums[j], nums[k]);
        // 4. 对[j+1, n-1]区间的元素从小到大排序,此时只需要反转下数字即可reverse
        std::reverse(nums.begin() + j + 1, nums.end());
    }
};

你可能感兴趣的:(leetcode最热100题,算法,数据结构,c++,leetcode,职场和发展)