有一类题目是让我们求元素左边或者右边下一个更大的元素,这类题目需要用到单调栈,详情可见 单调栈
而今天的「下一个更大元素」题目是让我们重新排列数字,找到大于n
的最小整数,和「下一个排列」很像,题目详情可见 下一个排列
题目详情可见 下一个排列
给定若干个数字,将其组合为一个整数。如何将这些数字重新排列,以得到下一个更大的整数。如123
下一个更大的数为 132
。如果没有更大的整数,则输出最小的整数
以 1,2,3
为例,其排列依次为:123 -> 132 -> 213 -> 231 -> 312 -> 321,该次序也符合从小到大的关系
如何得到这样的排列顺序?这是本文的重点。我们可以这样来分析:
我们希望下一个数比当前数大,这样才满足「下一个排列」的定义。因此只需要将后面的「大数」与前面的「小数」交换,就能得到一个更大的数。比如123
,将2
和3
交换就能得到一个更大的132
我们还希望下一个数增加的幅度尽可能的小,这样才满足「下一个排列与当前排列紧邻」的要求。为了满足这个要求,我们需要:
123465
,下一个排列应该把5
和4
交换而不是把6
和4
交换123465
为例:首先按照上一步,交换5
和4
,得到123564
;然后需要将5
之后的数重置为升序,得到123546
。显然123546
比123564
更小,123546
就是123465
的下一个排列以上就是求「下一个排列」的分析过程
以求12385764
的下一个排列为例:
首先从后向前查找第一个相邻升序的元素对(i, j)
。这里i = 4
,j = 5
,对应的值为5
,7
:
然后我们从j = 5; val = 7
开始排序,如绿色部分所示:
在绿色部分中从小到大开始找第一个比i = 4; val = 5
大的元素,并交换,即值5
和6
交换:
因此:12385764
(橙色部分) 的下一个排列就是 12386457
(绿色部分)
public void nextPermutation(int[] nums) {
int n = nums.length;
// 从后向前查找第一个相邻升序的元素对
for (int i = n - 1; i > 0; i--) {
if (nums[i] > nums[i - 1]) {
// 从 i 开始排序
Arrays.sort(nums, i, n);
// 从 i 开始向后找第一个比 i - 1 大的元素
for (int j = i; j < n; j++) {
// 找到就交换
if (nums[j] > nums[i - 1]) {
int temp = nums[j];
nums[j] = nums[i - 1];
nums[i - 1] = temp;
return ;
}
}
}
}
// 不存在下一个排列更大的排列
Arrays.sort(nums);
return ;
}
题目详情可见 下一个更大元素 III
过程基本上和上个题目分析一致,完整代码如下:
xxxxxxxxxx
public int nextGreaterElement(int n) {
// 转换成 char[]
char[] s = String.valueOf(n).toCharArray();
// 从后向前查找第一个相邻升序的元素对
for (int i = s.length - 1; i > 0; i--) {
if (s[i] > s[i - 1]) {
// 从 i 开始排序
Arrays.sort(s, i, s.length);
// 从 i 开始向后找第一个比 i - 1 大的元素
for (int j = i; j < s.length; j++) {
// 找到就交换
if (s[j] > s[i - 1]) {
char t = s[i - 1];
s[i - 1] = s[j];
s[j] = t;
// 判断是否为 32 位整数
long ans = Long.parseLong(String.valueOf(s));
if (ans > Integer.MAX_VALUE) return -1;
return (int) ans;
}
}
}
}
// 没有下一个更大的元素
return -1;
}