您的位置:首页 > 其它

笔试题73. LeetCode OJ (60)

2016-06-04 14:16 211 查看


Permutation Sequence

这个题是求1~n (n[1~9]) 的数字的全排列的第K个序列。

一般思路是:使用一个计数器,递归去找全排列序列,找到一个计数器加一,一直到第k个。

但是加若 n = 9 我要找的是第 (9! -1 )个数,那么上述办法的时间是多少,多半会超时的(没试过,但是我敢保证一定会超时的,因为这样的思路不可取),想一想我们只需要一个序列,并不必要把全部的序列都找出来吧。下面我给出一种解题方案,我个人感觉是可取的。

我们是学过数学的人,要我们求全排列的第 k 个序列,那么我们其实可以推测它的大致分布在那个范围(不是用眼睛看,而是推导出来的)。这个方法是这样的:

假设 n = 3,那么 1~3 组成的全排列以及相应的第K个序列氛围如下:

k n[1,3]
1 1 2 3
21 3 2
3 2 1 3
42 3 1
53 1 2
63 2 1
首先说明一下像这种无重复数字的全排列规律:

n = 1 时,全排列个数为: 1!

n = 2 时,全排列个数为: 2!

n = 3 时,全排列个数为: 3!

.....

基于这种规律我们是不是可以大致推测k的范围,推测的方法是去找一个数 m,时 m! > k,这样可以说明k的大致位置,画个图说一下思路吧。



上面所说的解题方法确实不好描述清楚,因为它是数字规律,我是通过过滤一些位置来不断缩小k的值,当缩小到 k = 1的时候所对应的序列就是我们要找的序列,如果还没看懂的话那就是我没有描述好的问题了。所以我教一个方法:

例如:

当:n = 2

1 2

2 1

那么我们交换1和2的位置(交换第一位和第二位的位置),就相当于过滤掉一个序列了,k的值也就减小 1

当:n = 3

1 2 3

1 3 2

2 1 3

2 3 1

3 1 2

3 2 1

所以当我们交换1和2的位置,我们就过滤了2个序列,相应的k的值也就减少了2,问题缩小为在两个数的全排列中寻找第k个序列

当我们交换1与3的位置,我们就过滤掉了4个序列,相应的k的值也就减少了 4,问题也缩小为在两个数的全排列中寻找第k个虚列

.... 所以这样就可以推导到 n = 4,5,6,7...,问题也就会不断缩小,最终缩小为1,问题解决,代码如下,可参考代码理解。

class Solution {
public:
string getPermutation(int n, int k)
{ //1~n 的全排列的 第k个数
string ret;
ret.clear();
if (n == 1 && k != 1 || k > factorial(n))
{
return ret;
}

vector<int> v;
v.clear();
for (int i = 1; i <= n; ++i)
{
v.push_back(i);
}

int begin = 0;
int pos = 0;

while (k > 0)
{
begin = 1;
int offset = 0;
int nums = 0;

while ((nums = factorial(begin)) < k)
{ //k分布在第begin位之后
++ begin;
}
nums /= begin;
pos = n - begin;  //第pos位可能需要交换

if (begin > n+1)
{ //不存在,其实是越界了,意思是k比 n!还大,不存在
return ret;
}

int temp = 0;
int jump = 0;  //去找
while (temp+nums < k)
{ //去找需要和那一位交换位置
temp += nums;
++jump; //jump指明了该位置的相对距离
}

if (jump > 0)
{
swap(v[pos], v[pos+jump]);
//交换位置后需要对后面的序列排序
sort(v.begin() + pos + 1, v.end());
}
//交换后,k的相对位置发生变化
k -= jump*nums;

if (k <= 1)
{ //这种情况说明此时就是要找的序列
for (int i=0;i<n;++i)
{
ret.push_back(v[i] + '0');
}
return ret;
}
}
return ret;
}

int factorial(int n)
{ //求阶乘
int ret = 1;
for (int i = 2; i <= n; ++i)
{
ret *= i;
}

return ret;
}
};
结果如下:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: