字典序算法

给定一个正整数,实现一个方法来求出离该整数最近的大于自身的换位数

换位数:把一个整数各个数位的数字进行全排列,从而得到新的整数。例如53241和23541。

例子:输入12345,返回12354

       输入12354,返回12435

       输入12435,返回12453

 

思路:给定整数12354,想找到最大换位数,需要尽量保持高位不变,低位在最小的范围内变换顺序

三个步骤:

1.从后向前查看逆序区域,找到逆序区域的前一位,也就是数字置换的边界

2.把逆序区域的前一位和逆序区域中刚刚大于它的数字交换位置

3.把原来的逆序区域转为顺序

   

public class 字典序算法 {
    //主流程,返回最近一个大于自身的相同数字组成的整数。
    public static int[] findNearestNumber(int[] numbers){
        //拷贝入参,避免直接修改入参
        int[] numbersCopy = Arrays.copyOf(numbers, numbers.length);
        //1.从后向前查看逆序区域,找到逆序区域的前一位,也就是数字置换的边界
        int index = findTransferPoint(numbersCopy);
        //如果数字置换边界是0,说明整个数组已经逆序,无法得到更大的相同数字组成的整数,返回自身
        if(index == 0){
            return null;
        }
        //2.把逆序区域的前一位和逆序区域中刚刚大于它的数字交换位置
        exchangeHead(numbersCopy, index);
        //3.把原来的逆序区域转为顺序
        reverse(numbersCopy, index);
        return numbersCopy;
    }

    private static int findTransferPoint(int[] numbers){
        for(int i=numbers.length-1; i>0; i--){
            if(numbers[i] > numbers[i-1]){
                return i;
            }
        }
        return 0;
    }

    private  static int[] exchangeHead(int[] numbers, int index){
        int head = numbers[index-1];
        for(int i=numbers.length-1; i>0; i--){
            if(head < numbers[i]){
                numbers[index-1] =  numbers[i];
                numbers[i] = head;
                break;
            }
        }
        return numbers;
    }

    private static int[] reverse(int[] num, int index){
        for(int i=index,j=num.length-1; i<j; i++,j--){
            int temp = num[i];
            num[i] = num[j];
            num[j] = temp;
        }
        return num;
    }

    public static void main(String[] args) {
        int[] numbers = {1,2,3,4,5};
        for(int i=0; i<10;i++){
            numbers = findNearestNumber(numbers);
            outputNumbers(numbers);
        }
    }

    //输出数组
    private static void outputNumbers(int[] numbers){
        for(int i : numbers){
            System.out.print(i);
        }
        System.out.println();
    }
}

 

参考链接:

https://mp.weixin.qq.com/s/_mIeGKdvTOH-1jleJ4aADg

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是C语言实现代码: ```c #include <stdio.h> // 计算n的阶乘 int factorial(int n) { int res = 1; for (int i = 1; i <= n; i++) { res *= i; } return res; } // 交换两个数 void swap(int *a, int *b) { int temp = *a; *a = *b; *b = temp; } // 字典序全排列 void permutation(int n) { int p[n]; // 初始化为1,2,3,...,n for (int i = 0; i < n; i++) { p[i] = i + 1; } int count = 0; do { count++; printf("%d\t", count); for (int i = 0; i < n; i++) { printf("%d", p[i]); } printf("\n"); } while (next_permutation(p, n)); } // 下一个字典序排列 int next_permutation(int *p, int n) { // 从后往前找到第一个相邻的逆序对 int i = n - 2; while (i >= 0 && p[i] >= p[i + 1]) { i--; } // 如果找不到逆序对,说明已经是最后一个排列,返回0 if (i < 0) { return 0; } // 从i的右侧找到最小的大于p[i]的数 int j = n - 1; while (j > i && p[j] <= p[i]) { j--; } // 交换p[i]和p[j] swap(&p[i], &p[j]); // 反转i右侧的元素 int k = i + 1, l = n - 1; while (k < l) { swap(&p[k], &p[l]); k++; l--; } return 1; } int main() { int n; printf("请输入一个整数n(1<=n<=9):"); scanf("%d", &n); int count = factorial(n); printf("%d!共有%d个全排列,输出如下:\n", n, count); permutation(n); return 0; } ``` 该程序使用了字典序全排列算法,先将1到n初始化为一个数组p,然后按照字典序的顺序依次输出全排列,直到输出了n!个全排列。在每次输出时,先输出当前排列的编号,然后再输出该排列的元素。在next_permutation函数中,实现了求下一个字典序排列的算法
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值