zoukankan      html  css  js  c++  java
  • LeetCode:60. Permutation Sequence,n全排列的第k个子列

    LeetCode:60. Permutation Sequence,n全排列的第k个子列 :

    题目:

    LeetCode: 60. Permutation Sequence

    描述:

    The set [1,2,3,…,n] contains a total of n! unique permutations.
    By listing and labeling all of the permutations in order,
    We get the following sequence (ie, for n = 3):
    "123"
    "132"
    "213"
    "231"
    "312"
    "321"
    Given n and k, return the kth permutation sequence.
    Note: Given n will be between 1 and 9 inclusive.
    简要概括内容 :寻找到给定n的集合(n = 3 ,[1,2,3]),寻找它的kth个全排列子列。

    分析:

    方法一: 利用STL中的next_permutation函数实现
    特点:代码简洁,暴力枚举

    方法二: 利用康托逆展开的方式进行快速寻找,关于康托展开
    特点:快速有效

    代码:

    string getPermutationEx(int n, int k)
    {
        string s(n, '0');
        for (int i = 0; i < n; ++i)
        {
            s[i] = i + 1;
        }
        for (int i = 0; i < k - 1; ++i)
        {
            next_permutation(s.begin(), s.end());
        }
    
        return s;
    }
    
    string getPermutation(int n, int k)
    {
        string strTemp(n, '0');
        string strRes;
        for (int i = 0; i < n; ++i)
        {
            strTemp[i] += i + 1;
        }
    
        int nNum = 1;
        int nTemp = n;
        while (0 != --nTemp)
        {
            nNum *= nTemp;
        }
    
        int kTemp = k - 1;
        int nA;
    
        nTemp = n - 1;
        for (auto iterBg = strTemp.begin(); iterBg != strTemp.end();)
        {
            nA = kTemp / nNum; // a = k / (n - 1)!;
            kTemp = kTemp % nNum; // k = k % (n - 1)!;
            strRes.push_back(strTemp[nA]);
            strTemp.erase(iterBg + nA);
    
            nNum = nNum / (nTemp ? nTemp : 1);
            --nTemp;
        }
    
        return strRes;
    }    
    
    

    /***********************2017年5月3日更新*******************************************/

    测试代码:

        // test for Permutation Sequence
        int main()
        {
            string s = getPermutation(1, 1);
            for (int i = 0; i < s.size(); ++i)
            {
                printf("%c", s[i]);
            }
        }
    
    

    备注:

    此处对康托逆展开做一个说明:
    为了寻找到 n = 5 , k = 6的子序列步骤如下:

    1. n = 5,则说明初始序列为“12345”,使用a1、a2、a3、a4、a5表示;
    2. 根据康托逆展开中描述,该序列变化了k = k - 1 = 5次,即在 “12345“的第五个序列
    3. a1 = k / (n - 1)! = 5 / 4! = 0; // 整除 第一位数字为比“1”大0的数字“1”
    4. k1 = k % (n - 1)! = 5 % 4! = 5; // k1 作为下一次运算的k 带入算式
    5. a2 = k1 / (n - 2)! = 5 / 3! = 0; //整除 第二位数字为比“2”大0的数字,“1” 已经被“取”走所以此处取“2”
    6. k2 = k1 % (n - 2)! = 5 % 3! = 5; // k2 作为下一次运算的k 带入算式
    7. a3 = k2 / (n - 3)! = 5 / 2! = 2; //整除 第三位数字为比“3”大2的数字,(“1”“2” 已经被“取”走)此处取“5”
    8. k3 = k2 % (n - 3)! = 5 % 2! = 1; // k3 作为下一次运算的k 带入算式
    9. a4 = k2 % (n - 4)! = 1 / 1 = 1; // 第四位数字为比“3”大1的数字,(“1”“2” 已经被“取”走)此处取“4”
    10. k4 = k3 % (n - 4)! = 5 % 2! = 0; // k3 作为下一次运算的k 带入算式
    11. a5 为剩余的 “3”;// 当然程序设计的时候只需要对 (n - i)!进行非0处理就可以了,不需要单独进行循环外处理。

    算法逻辑:

    1. 通过n,k创建初始化的 strTemp;
    2. 开始寻找第K序列;// 第k = k - 1个
    1. 寻找a1 ; // a = k / (n - 1)!;
    2. k = k % (n - 1)!;
    3. 将a存入 输出数据strRes中;
    4. 移除str[a1]元素
      重复上述。

    谢谢小伙伴提的意见,后续博客会更新leetcode相关内容。本来不打算写下来的,毕竟leetcode题目博客在网上一大抄,但是个人还是觉得吸取大家的意见,顺路巩固加强下自己的理解,好记性不如烂笔头!

  • 相关阅读:
    VS自带的诊断工具
    Electron学习
    PC跨*台
    .NET调试学习
    Mac使用
    SSL/TLS
    UKey学习
    授权机制OAuth、JWT
    代理服务器
    .NET相关源码查找
  • 原文地址:https://www.cnblogs.com/liuwfuang96/p/6821507.html
Copyright © 2011-2022 走看看