zoukankan      html  css  js  c++  java
  • next permutation 的实现

     参考博客:https://www.cnblogs.com/DWVictor/p/10301666.html

    https://www.cnblogs.com/xingzhg/p/3927453.html

    一,思路

    观察全排列的第一个 12345 和 最后一个 54321 可以发现

    全排列的第一个排列是升序的,最后一个排列是降序的,

    这一点能得到什么 结论呢 ?(敲黑板,画重点)

    当然是—— 只看 降序 部分的话,没有下一序列,也就是说—— 想要有下一序列的话,必须出现 升序对 ,不连在一起也还 OK 啦 

    今天我们就用这一点解决如何某一排列的下一个。

    如何利用这一点呢 ?

    给定排列:21354 ,如何得到下一排列呢 ?

       ①    因为是按字典序排序的,所以下一个是 比他大的最小值,所以我们先从后面观察,因为后面的数变了,大小差的小。

       ②    又因为由相同数字组成的,所以要得到下一个数,一定会经过数字的易位,所以我们要观察的不能是一个数,至少是两个数。

    接下来就是重头戏了,( ‘-ωก̀ )

    根据 ①② 两点及上面的推论,

    我们先看 54,不行,是 降序 的,抬走下一个

    我们再看 354,出现了 升序对了,可以,这时候怎么办呢?

    不要慌,喝口药。蛇皮走位,观察战局,我们发现 改变绝对不可能只在 54 之间发生(这一点就是之前看 54 时候排除的)

    所以我们找到了机会,就是 3 一定参与改变,这时候为了满足 ①,我们只要在  3 后面找到一个最小的比 3 大的数,两者易位,然后再把 后面的 降序 逆序 成 升序 就可以了

    所以,找到 4,得到 453,逆序后面的数,得到 435,最后结果为 21435

    此时,推广至任意序列:

    给定任意排列: ABCDE    (他们的分别代表 1,2,3,4,5,位置任意)

     观察 DE,若 DE 升序,两者交换,得到结果。

                      若 DE 降序,待定,加下一个数字

                      观察 CDE ,若 CDE 升序 (不可能出现这种情况了,之前已经排除了)                                    

                                           若 CDE 既有升序,又有降序,则必有,CD 升序,DE 降序(因为 DE 已然 降序 )

                                            所以此时,C 必改变(因为只有 DE 改变的,之前已经排除了),

                                           所以在后面找一个比 C 大的最小的数,因为 CD 升序,DE 降序,所以从最后一位开始向前查找,第一个比 C 大的就是了。

                                           然后将找到的数字与 C 交换,然后再把原先 C  位置后面的 降序 逆序 成 升序 就可以了,得到结果

                                           若 CDE 降序,待定,加下一个数字

               观察 BCDE,重复上述操作。。。。。。。

                                                                   若最后 ABCDE 是 降序的,则没有下一个序列,返回 0,当然为了特定情况,可以认为 EDCBA 即第一个序列,是最后一个序列的下一个。

     到此终了,其他一些细节可见代码的注释.

    题目:

    给出正整数n,则1 到n 这n 个数可以构成n!种排列,把这些排列按照从小到大的顺序(字典顺序)列出,如n = 3 时,列出1 2 3,1 3 2,2 1 3,2 3 1,3 1 2,3 2 1 六个排列。

    任务描述: 给出某个排列,求出这个排列的下k 个排列,如果遇到最后一个排列,则下1 排列为第1个排列,即排列1 2 3…n。

    比如:n = 3,k = 2 给出排列2 3 1,则它的下1 个排列为3 1 2,下2 个排列为3 2 1,因此答案为3 2 1。

    #define _CRT_SECURE_NO_WARNINGS
    #include<string.h>
    #include<stdio.h>
    #include<stdlib.h>
    void swap(char *s1, char *s2)
    {
        char t = *s1;
        *s1 = *s2;
        *s2 = t;
    }
    void reverse(char *s, char* e) 
    {
        for (e--; s < e; s++, e--)
            swap(s, e);
    }
    int next(char* begin, char* end)  // begin 指向s[0].end 指向 ''
    {
        if (begin == end)   // 如果没有元素
            return 0;
        if (++begin == end) // 如果只有一个元素
            return 0;
        begin--;
    
        char *i = end;
        i--;          
        while (1)   // i,j 从后面往前查找  查找第一对出现 升序 的相邻元素,则 i 后面肯定是 降序 的1
        {
            char* j = i;  // j 指向最后一个元素
            i--;          // i 在 j 前面
    
            if (*i < *j)   //  i 代表右边都是降序的最小的下标值。
            {
                char* k = end;
                while (*i >= *--k)      // 在右边 找到第一个大于 i 的值, 
                    ;
                swap(i, k);            // 交换两者的之值, 
                reverse(j, end);       // 逆序  右边的降序变成 升序
                return 1;
            }
            if (i == begin)   // 整体升序,所以是最后一个排列,所以下一个就是第一个排列,也就是 最后一个排列的逆序
            {
                reverse(begin, end);
                return 0;
            }
        }
    }
    int main(void)
    {
        printf("请输入 n 和 k 的值:");
        int  n, k;
        char a[100];
        scanf("%d%d", &n, &k);
        printf("请输入给定的序列:");    
        for (int i = 0; i < n; i++)
        {
            scanf(" %c", &a[i]);
        }
    
        for (int i = 0; i < k; i++)
            next(a, a + n);
    
        printf("该序列的下 %d 个是:", k);    
        for (int i = 0; i < n; i++)
        {
            printf("%c ", a[i]);
        }puts("");
    
        system("pause");
        return 0;
    }
    /*
    测试数据
    3 1
    3 2 1
    */

    ========== ======== ======= ====== ===== ==== ==== === == =

    stop ! stop it Ray ! Even if you are facing a bitter  aspect of life , drugs and murder are foul without any excuse ,

    deserve a red card  for a loser .                         ——  Conan

    True , I was a cheater , a bad player and I lost the game . I must be adjudicative ,

    for both my late wife and a fan like you .            —— Ray

  • 相关阅读:
    axios封装
    python 分析列表中的字典
    python 列表解析学习
    Java常用ORM框架
    Kafka 会不会丢消息?怎么处理的?
    Node.js学习笔记【八】
    Node.js学习笔记【七】
    Node.js学习笔记【六】
    Node.js学习笔记【五】
    Node.js学习笔记【四】
  • 原文地址:https://www.cnblogs.com/asdfknjhu/p/12989203.html
Copyright © 2011-2022 走看看