# 31. 下一个排列 (Medium)

## 问题描述
[31. 下一个排列][link] (Medium)

[link]: https://leetcode.cn/problems/next-permutation/

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

- 例如， `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` 的下一个排列。

必须 **[原地](https://baike.baidu.com/item/%E5%8E%9F%E5%9C%B0%E7%AE%97%E6%B3%95)** 修改，只允许使用
额外常数空间。

**示例 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`

## 解题思路

要找到下一个排列，假设我们需要交换 `nums[l]` 和 `nums[r]`，需要满足这样的约束条件：

1. $l$ 尽可能大；
2. 在 $l$ 尽可能大的情况下，$nums[r]$ 尽可能小。

完成交换后，对 `l` 之后的元素从小到大排序。

我们需要从右往左遍历，使用一个单调递增栈，如果当前元素大于等于栈顶元素，即将当前元素的索引入栈，否则，$l$ 就是当前元素的索引，$r$ 就是栈中满足 $nums[r] > nums[l]$ 的最小的 `nums[r]` 对应的 $r$。

这里其实不需要使用栈，从右往左遍历两次即可，第一次寻找 $l$，第二次寻找 $r$。

## 代码

```cpp
class Solution {
  public:
    void nextPermutation(vector<int> &nums) {
        int n = nums.size();
        int resr = 0, resl = -1;
        int rnum = nums[n - 1], lnum = nums[n - 1];
        for (int i = n - 1; i >= 0; --i) {
            if (nums[i] >= rnum) {
                resr = i;
                rnum = nums[i];
            } else if (nums[i] < rnum) {
                resl = i;
                lnum = nums[i];
                break;
            }
        }
        for (int i = n - 1; i > resl; --i) {
            if (nums[i] > lnum && nums[i] < rnum) {
                resr = i;
                rnum = nums[i];
            }
        }
        if (resl < 0) {
            sort(nums.begin(), nums.end());
        } else {
            swap(nums[resl], nums[resr]);
            sort(nums.begin() + resl + 1, nums.end());
        }
    }
};
```


