题目:
// 给定任意一个自然数,获取它重新排列后,下一个比它大的自然数,要求时间复杂度O(n)。例如:
// 给定1233,它的下一个是1323;
// 给定1323,它的下一个是1332;
// 给定9876,它的下一个不存在;
// 请设计一个函数,完成此功能。(语言不限)
具体解决思路在注释中写的很详细了
package ChuJiSuanFa.src;
import java.util.ArrayList;
public class exam
{
public static void main(String[] args)
{
System.out.println("题目2:");
int num = 1323;
String result = exam2(num);
System.out.println("数字 " + num + "比他大的排列为" + result);
}
// 给定任意一个自然数,获取它重新排列后,下一个比它大的自然数,要求时间复杂度O(n)。例如:
// 给定1233,它的下一个是1323;
// 给定1323,它的下一个是1332;
// 给定9876,它的下一个不存在;
// 请设计一个函数,完成此功能。(语言不限)
static String exam2(int num)
{
// 创建空数组
ArrayList<Integer> nums = new ArrayList<>();
// 分解自然数并放入数组
while ((num % 10) > 0) {
int tmp = num % 10;
num = num / 10;
nums.add(0, tmp);
}
// 为了和原数接近,我们需要尽量保持高位不变,低位在最小的范围内变换顺序。
// 0.从后向前查看逆序区域,找到逆序区域的前一位,也就是数字置换的边界
int criticalPoint = findCriticalPoint(nums);
// 1.首先检查是否为最大值
if (criticalPoint == -1) {
return "不存在";
}
// 2.把逆序区域的前一位和逆序区域中刚刚大于它的数字交换位置并把原来的逆序区域转为顺序
return reorder(nums, criticalPoint).toString();
}
static int findCriticalPoint(ArrayList<Integer> nums)
{
for (int i = nums.size() - 1; i > 0; i--) {
if (nums.get(i) > nums.get(i - 1)) {
// 如果找到临界值,返回那个值
return i;
}
}
// 没找到,代表该数组每个数都比后面的数大也就是逆序排列
return -1;
}
static ArrayList<Integer> reorder(ArrayList<Integer> nums, int index)
{
int left = nums.get(index - 1);
for (int i = nums.size() - 1; i >= index; i--) {
int right = nums.get(i);
if (left < right) {
nums.set(index - 1, right);
nums.set(i, left);
break;
}
}
for (int i = index, j = nums.size() - 1; i < j; i++, j--) {
int temp = nums.get(i);
nums.set(i, nums.get(j));
nums.set(j, temp);
}
return nums;
}
}