C++ 笔试每日一题(leetcode 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=3,k=3,f返回的排序串为“213”

继续举例子:1234,k=12

一共有total=4 * 3 * 2 * 1种情况

其中第一位是1的有3 * 2 * 1种
其中第一位是2的有3 * 2 * 1种
其中第一位是3的有3 * 2 * 1种
其中第一位是4的有3 * 2 * 1种

//需要注意的是数组的下标是从0 开始的,即index=0  对应是1

index=1 ,对应的值为2;  index=2,对应的值为3

(12 - 1) / 3! = 1余5,第一位是2
(5+1 - 1 ) / 2! = 2余1,第二位是4(余数+1=1)
(1+1 - 1) / 1! = 1余0,第三位是3

参考博客:https://www.cnblogs.com/grandyang/p/4358678.html 

#include <iostream>
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
#include <string>
using namespace std;
/*
 *Permutation sequence
*/
class solutin1{
public:
    /**
     * @brief getPermutation
     * @param n:一个排序列由n个数组成
     * @param k: 第k个排序列
     * @return :string 类型
     */
    string getPermutation(int n,int k){

        string s("123456789");
        string str=s.substr(0,n);//拷贝字符串s中从第0位开始的长度为n的字符串
        string res(n,' '); //要分配足够,否则会出现越界错误
        for(int i=0;i<n;i++){
            res[i]=helper(str,k);
        }
        return res;
    }
//为什么取s[i]呢?因为对于数组s而言,里面的元素虽然每一轮都会删除一个,
//但始终保证按从小到大排序(因为数组s最初就是1,2,3,...,n,删掉元素不会打乱其有序性)
//因此,在数组s中有且仅有i个元素比s[i]小。(即s[i]是数组中由小到大排序的第i+1个数)
//而由于我们当前所计算的c是当前所处理子串的最高位,而且i= (k-1)/tmp意味着最高位的这个数字应该满足其后有且只有i个元素比它小,
//由于是最高位,因此其后有i个元素就意味着这是一个在当前数组由小到大排序的第i+1个数。因此s[i]就是我们想找的那个数。
      char helper(string &s,int& k)   
    {
      int tmp=factorial(s.size()-1);
      int i=(k-1)/tmp;  //商值决定了第几组
      char c=s[i];      //s[i]是数组中的由小到大的排序的第i+1个数
      s.erase(i,1);     //在数组的第i位删除一位数字 ,删除的数据送入数组中进行存储
      k-=tmp*i;         //得到余数,
      return c;     
    }
    /*阶乘计算*/
    int factorial(int n)
    {
        int result=1;
        if(n==0)  return 1;
        for(int i=2;i<=n;i++)
        {
          result*=i;
        }
        return result;
    }
};
class solution{
public:

    /**
    * @brief next_permutation
    * @param nums
    */
   void  next_permutation(vector<int>& nums)
   {
   int n=nums.size();
   int i=n-2;
   int j=n-1;
   /*从后往前看,到第一个开始降序的地方*/
   while(i>=0&&nums[i]>nums[i+1]) --i;
   if(i>=0){
   /*再从后面往前找第一个大于刚刚降序的那个位置的数字*/
       while(nums[j]<=nums[i])  --j;
       swap(nums[i],nums[j]);
   }
     reverse(nums.begin()+i+1,nums.end());//注意数组的下标是从0开始的
   }
};

void  display(const int&  data)
{
    cout<<data<<' ';
}
int main(int argc, char *argv[])
{
//    int   a[]={1,1,5};
//    vector<int>  vec(a,a+sizeof(a)/sizeof(int));
//    vector<int>::iterator iter;
//    cout<<"vec.begin():"<<*vec.begin()<<endl;
//    for_each(vec.begin(),vec.end(),display);
//    solution sl;
//    sl.next_permutation(vec);
//    cout<<endl;
//    for_each(vec.begin(),vec.end(),display);
    cout<<endl;
    solutin1 s2;
    cout<<s2.getPermutation(4,12);
    return 0;
}

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值