|
| 1 | +### 题目描述 |
| 2 | + |
| 3 | +这是 LeetCode 上的 **[556. 下一个更大元素 III](https://leetcode.cn/problems/next-greater-element-iii/solution/by-ac_oier-99bj/)** ,难度为 **中等**。 |
| 4 | + |
| 5 | +Tag : 「模拟」、「双指针」 |
| 6 | + |
| 7 | + |
| 8 | + |
| 9 | +给你一个正整数 $n,ドル请你找出符合条件的最小整数,其由重新排列 $n$ 中存在的每位数字组成,并且其值大于 $n$。如果不存在这样的正整数,则返回 $-1$ 。 |
| 10 | + |
| 11 | +注意 ,返回的整数应当是一个 32ドル$ 位整数 ,如果存在满足题意的答案,但不是 32ドル$ 位整数 ,同样返回 $-1$。 |
| 12 | + |
| 13 | +示例 1: |
| 14 | +``` |
| 15 | +输入:n = 12 |
| 16 | + |
| 17 | +输出:21 |
| 18 | +``` |
| 19 | +示例 2: |
| 20 | +``` |
| 21 | +输入:n = 21 |
| 22 | + |
| 23 | +输出:-1 |
| 24 | +``` |
| 25 | + |
| 26 | +提示: |
| 27 | +* 1ドル <= n <= 2^{31} - 1$ |
| 28 | + |
| 29 | +--- |
| 30 | + |
| 31 | +### 模拟 |
| 32 | + |
| 33 | +根据题意,只有给定数字 $x$ 本身从高位到低位是「非严格降序」时,我们无法找到一个合法值。 |
| 34 | + |
| 35 | +首先,我们可以先对 $x$ 诸位取出,存成 `nums` 数组(数组的首位元素为原数 $x$ 的最低位)。 |
| 36 | + |
| 37 | +然后尝试找到第一个能够交换的位置 `idx`(若无法找到,说明不存在合法值,返回 $-1$),即从 $nums[0]$(原始 $x$ 的最低位)开始找,找到第一个「降序」的位置 `idx`,然后从 $[0, idx)$ 范围内找一个比 $nums[idx]$ 要大的最小数与其进行互换,也是从 $nums[0]$ 开始找,找到第一个满足比 $nums[idx]$ 大的数。 |
| 38 | + |
| 39 | +当互换完成后,此时比 $x$ 要大这一目标已由第 `idx` 位所保证(后续的排序应该按照从小到大放置),同时互换结束后的 $[0, idx)$ 仍然满足「非严格升序」特性,因此我们可以对其运用「双指针」进行翻转。 |
| 40 | + |
| 41 | +代码: |
| 42 | +```Java |
| 43 | +class Solution { |
| 44 | + public int nextGreaterElement(int x) { |
| 45 | + List<Integer> nums = new ArrayList<>(); |
| 46 | + while (x != 0) { |
| 47 | + nums.add(x % 10); |
| 48 | + x /= 10; |
| 49 | + } |
| 50 | + int n = nums.size(), idx = -1; |
| 51 | + for (int i = 0; i < n - 1 && idx == -1; i++) { |
| 52 | + if (nums.get(i + 1) < nums.get(i)) idx = i + 1; |
| 53 | + } |
| 54 | + if (idx == -1) return -1; |
| 55 | + for (int i = 0; i < idx; i++) { |
| 56 | + if (nums.get(i) > nums.get(idx)) { |
| 57 | + swap(nums, i, idx); |
| 58 | + break; |
| 59 | + } |
| 60 | + } |
| 61 | + for (int l = 0, r = idx - 1; l < r; l++, r--) swap(nums, l, r); |
| 62 | + long ans = 0; |
| 63 | + for (int i = n - 1; i >= 0; i--) ans = ans * 10 + nums.get(i); |
| 64 | + return ans > Integer.MAX_VALUE ? -1 : (int)ans; |
| 65 | + } |
| 66 | + void swap(List<Integer> nums, int a, int b) { |
| 67 | + int c = nums.get(a); |
| 68 | + nums.set(a, nums.get(b)); |
| 69 | + nums.set(b, c); |
| 70 | + } |
| 71 | +} |
| 72 | +``` |
| 73 | +* 时间复杂度:$O(\log{n})$ |
| 74 | +* 空间复杂度:$O(\log{n})$ |
| 75 | + |
| 76 | +--- |
| 77 | + |
| 78 | +### 最后 |
| 79 | + |
| 80 | +这是我们「刷穿 LeetCode」系列文章的第 `No.556` 篇,系列开始于 2021年01月01日,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。 |
| 81 | + |
| 82 | +在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。 |
| 83 | + |
| 84 | +为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode 。 |
| 85 | + |
| 86 | +在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。 |
| 87 | + |
0 commit comments