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

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”
6. k3 = k2 % (n - 3)! = 5 % 2! = 1; // k3 作为下一次运算的k 带入算式
7. a4 = k2 % (n - 4)! = 1 / 1 = 1; // 第四位数字为比“3”大1的数字,(“1”“2” 已经被“取”走)此处取“4”
8. k4 = k3 % (n - 4)! = 5 % 2! = 0; // k3 作为下一次运算的k 带入算式
9. 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题目博客在网上一大抄,但是个人还是觉得吸取大家的意见,顺路巩固加强下自己的理解,好记性不如烂笔头!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
给定一个整数数组 nums 和一个目标值 target,要求在数组中找出两个数的和等于目标值,并返回这两个数的索引。 思路1:暴力法 最简单的思路是使用两层循环遍历数组的所有组合,判断两个数的和是否等于目标值。如果等于目标值,则返回这两个数的索引。 此方法的时间复杂度为O(n^2),空间复杂度为O(1)。 思路2:哈希表 为了优化时间复杂度,可以使用哈希表来存储数组中的元素和对应的索引。遍历数组,对于每个元素nums[i],我们可以通过计算target - nums[i]的值,查找哈希表中是否存在这个差值。 如果存在,则说明找到了两个数的和等于目标值,返回它们的索引。如果不存在,将当前元素nums[i]和它的索引存入哈希表中。 此方法的时间复杂度为O(n),空间复杂度为O(n)。 思路3:双指针 如果数组已经排序,可以使用双指针的方法来求解。假设数组从小到大排序,定义左指针left指向数组的第一个元素,右指针right指向数组的最后一个元素。 如果当前两个指针指向的数的和等于目标值,则返回它们的索引。如果和小于目标值,则将左指针右移一位,使得和增大;如果和大于目标值,则将右指针左移一位,使得和减小。 继续移动指针,直到找到两个数的和等于目标值或者左指针超过了右指针。 此方法的时间复杂度为O(nlogn),空间复杂度为O(1)。 以上三种方法都可以解决问题,选择合适的方法取决于具体的应用场景和要求。如果数组规模较小并且不需要考虑额外的空间使用,则暴力法是最简单的方法。如果数组较大或者需要优化时间复杂度,则哈希表或双指针方法更合适。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值