556. 下一个更大元素 III
题目描述
给定一个32位正整数 n,你需要找到最小的32位整数,其与 n 中存在的位数完全相同,并且其值大于n。如果不存在这样的32位整数,则返回-1。
类似于求:LeetCode31题——下一个排列
参考思路:线性扫描,时间复杂度O(n)
算法思想:把 n 转为为字符数组 arr ,然后从后往前看,找到第一个下降的位置 i,然后让再从后往前找到第一个比 i 位置的值大的数,交换这两个位置,再逆序i后面的所有字符。
举例理解:
n: 12544321
n: 12|544321
从后往前看第一个严格下降的数是2
然后再从后往前看第一个比2大的数是3
于是交换2和3
得到13|544221
最后逆序544221这一段
得到最终答案13122445
class Solution {
public int nextGreaterElement(int n) {
// base case
if(n <= 0 || n == Integer.MAX_VALUE) {
return -1;
}
char[] arr = String.valueOf(n).toCharArray();
int len = arr.length;
int start = -1;
for(int i = len - 1; i >= 1; i--) {
// 从后往前看第一个不满足递增的数
if(arr[i] > arr[i - 1]) {
start = i - 1;
break;
}
}
if(start == -1) {
return -1;
}
// 从后往前找第一个大于等于arr[start]的数
for(int j = len - 1; j > start; j--) {
if(arr[j] > arr[start]) {
swap(arr, start, j);
break;
}
}
// 将start~len-1进行逆序
for(int p = start + 1, q = len - 1; p < q; p++, q--) {
swap(arr, p, q);
}
long sum = 0;
for(int k = 0; k < len; k++) {
sum = sum * 10 + (arr[k] - '0');
}
return sum > Integer.MAX_VALUE ? -1 : (int)sum;
}
public void swap(char[] arr, int i, int j) {
char ch = arr[j];
arr[j] = arr[i];
arr[i] = ch;
}
}
时间复杂度是O(n):最多扫描两次字符串
空间复杂度是O(n):使用了长度为n的数组存储数字的每个位