LeetCodeT31.下一个排列

在这里插入图片描述

解题思路及代码:

/*
    算法概述:这个题实际上是要找下一个更大的数
    要想得到下一个更大的数,就需要将后面的数与前面的数进行交换;
    而且,要想让下一个数增大的幅度最小,就需要尽可能的在右端发生交换,所以需要从后往前查找。
    那么问题来了,如何找到需要交换的两个数呢?
    原则是后面的大数和前面的小数进行交换,那么可以先从后往前越过序列中的降序序列(如果有的话),
    找到第一个相邻的升序数对(i,j),i<j,为什么是找相邻的呢,因为判断后面的降序序列用的就是相邻
    两个数的大小关系,当发现不是降序的时候自然也是从相邻的数发现的。
    然后从最后一个数往j开始找,找第一个比i大的数(保证交换的大数是最小的大数)与i交换,
    交换之后j之后的数必然也是降序,这时不要忘了我们的目的是让下一个数增大的幅度最小,现在
    把后面的大数换到前面了,那么要想使幅度最小,必须让j后面的数升序排列。

    害,写的貌似有点乱,这个逻辑我理解了好久……
*/
void sort(int* nums, int s, int e) {
    int i = 0, j = 0;
    int temp = 0;

    for (i = e; i > s; i--) {
        for (j = s; j < i; j++) {
            if (nums[j] > nums[j + 1]) {
                temp = nums[j];
                nums[j] = nums[j + 1];
                nums[j + 1] = temp;
            }
        }
    }
}

void nextPermutation(int* nums, int numsSize){
    int temp = 0;
    int i = 0, j = 0;

    for (i = numsSize - 1; i > 0; i--) {
        if (nums[i] > nums[i - 1]) {// 相邻的一个升序序列
            break;
        }
    }

    if (i == 0) {// 原序列为一个降序序列,则逆序输出
        for (i = numsSize - 1; i >= 0; i--)
            printf("%d ", nums[i]);
            
        printf("\n");
        return ;
    }

    for (j = numsSize - 1; j >= i; j--) {// 找最小的大数与前面的小数交换
        if (nums[j] > nums[i - 1]) {
            temp = nums[j];
            nums[j] = nums[i - 1];
            nums[i - 1] = temp;
            break;
        }
    }

    sort(nums, i, numsSize - 1);// 将后面的数排为升序,使得下一个更大的数最小

    for (i = 0; i < numsSize; i++)
        printf("%d ", nums[i]);
    printf("\n");
}

我无语了……
在这里插入图片描述
害,原来这个题是不要输出的,只要数组里面的值变了就行

通过的代码:

/*
    算法概述:这个题实际上是要找下一个更大的数
    要想得到下一个更大的数,就需要将后面的数与前面的数进行交换;
    而且,要想让下一个数增大的幅度最小,就需要尽可能的在右端发生交换,所以需要从后往前查找。
    那么问题来了,如何找到需要交换的两个数呢?
    原则是后面的大数和前面的小数进行交换,那么可以先从后往前越过序列中的降序序列(如果有的话),
    找到第一个相邻的升序数对(i,j),i<j,为什么是找相邻的呢,因为判断后面的降序序列用的就是相邻
    两个数的大小关系,当发现不是降序的时候自然也是从相邻的数发现的。
    然后从最后一个数往j开始找,找第一个比i大的数(保证交换的大数是最小的大数)与i交换,
    交换之后j之后的数必然也是降序,这时不要忘了我们的目的是让下一个数增大的幅度最小,现在
    把后面的大数换到前面了,那么要想使幅度最小,必须让j后面的数升序排列。

    害,写的貌似有点乱,这个逻辑我理解了好久……
*/
void reverse(int* nums, int s, int e) {
    int i = 0;
    int temp = 0;

    for (i = s; i <= (s + e) / 2; i++) {
        temp = nums[i];
        nums[i] = nums[s + e - i];
        nums[s + e - i] = temp;
    }
}

void nextPermutation(int* nums, int numsSize){
    int temp = 0;
    int i = 0, j = 0;

    for (i = numsSize - 1; i > 0; i--) {
        if (nums[i] > nums[i - 1]) {// 相邻的一个升序序列
            break;
        }
    }

    if (i == 0) {// 原序列为一个降序序列,则逆序排列
        reverse(nums, 0, numsSize - 1);
        return ;
    }

    for (j = numsSize - 1; j >= i; j--) {// 找最小的大数与前面的小数交换
        if (nums[j] > nums[i - 1]) {
            temp = nums[j];
            nums[j] = nums[i - 1];
            nums[i - 1] = temp;
            break;
        }
    }

    reverse(nums, i, numsSize - 1);// 逆序,使得下一个更大的数最小

    for (i = 0; i < numsSize; i++)
        printf("%d ", nums[i]);
    printf("\n");
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值