60.Permutation Sequence-Leetcode
2018-01-15 本文已影响2人
analanxingde
基础回顾
String
头文件中必须包括<string>
string的声明初始化
string s1 = "abcdefg"; //初始化方式1
string s2("abcdefg"); //初始化方式2
string s3 = s2; //通过拷贝构造函数 初始化s3
string s4(7,'s'); //初始化7个s的字符串
遍历
1.str[i]
2.迭代器:
for(string::iterator it = s1.begin(); it!= s1.end(); it++)
{
cout << *it << " ";
}
3.str.at[i]//此方式可以在越界时抛出异常
string与char*
//字符指针和字符串的转换
void strConvert()
{
cout << "字符指针和字符串的转换:" <<endl;
string s1 = "abcdefg"; //初始化字符串
cout << "string转换为char*:" <<endl;
//string转换为char*
cout << s1.c_str() <<endl; //s1.c_str()即为s1的char *形式
cout << "char*获取string内容:" <<endl;
//char*获取string内容
char buf[64] = {0};
s1.copy(buf, 7);//复制7个元素
cout << buf <<endl;
}
字符串连接
s1.append(s2);
s1+=s2;
string与int转化(注意stringstream)
//int与char*
char* n=a+'0'
itoa(num, str, 10); //stdlib.h中的函数
//int to string,其余类型之间转换也可参考类似的方法stringstream可以stringstream可以吞下任何类型,根据实际需要吐出不同的类型。
stringstream stream;//<sstream>
stream<<n;
stream.str();//stream>>str;
//string to int
n = atoi(str.c_str())
我的算法(受nextPermutation影响大,算法效率低)
nextPermutation算法思想:
https://www.nayuki.io/page/next-lexicographical-permutation-algorithm
#右数第一个非降序序列的前一个元素下标pivot
#右数第一个大于s[pivot]的值的下标设为successor
#交换successor与pivot对应的元素
#将pivot右边的所有元素逆序
class Solution {
//初始化s,后根据k进行循环限制,每次都取下一个排列数(根据NextPermutation的算法):效率很低
public:
string getPermutation(int n, int k) {
int i,j=0;
for(i=1;i<=n;i++)
{
j=j*10+i;
}
n=j;
stringstream ss;
string begin;
ss<<n;
begin=ss.str();
if(n==1 ||k==1)
{
return begin;
}
for(i=2;i<=k;i++)
{
begin=NextPermutation(begin);
}
return begin;
}
string NextPermutation(string s){
int len=s.length();
int i=len-1;
while(s[i]<=s[i-1] && i-1>=0)
{
i-=1;
}
int pivot=i-1; #右数第一个非降序序列的前一个元素下标pivot
int successor;
for(i=len-1;i>pivot;i--)
{
if(s[i]>s[pivot])
{
successor=i;
break; #右数第一个大于s[pivot]的值的下标
}
}
char middle=s[successor];
s[successor]=s[pivot];
s[pivot]=middle; #交换successor与pivot对应的元素
int j;
for (i=pivot+1,j=len-1;i<j;i++,j--)
{ #将pivot右边的所有元素逆序
middle=s[i];
s[i]=s[j];
s[j]=middle;
}
return s;
}
};
最优解法
http://blog.csdn.net/cinderella_niu/article/details/42927119
主要思想是按阶乘表示可能的组合种类:
1,2,3,… , n构建的全排列中,返回第k个排列。
题目告诉我们:对于n个数可以有n!种排列;那么n-1个数就有(n-1)!种排列。
那么对于n位数来说,如果除去最高位不看,后面的n-1位就有 (n-1)!种排列。
所以,还是对于n位数来说,每一个不同的最高位数,后面可以拼接(n-1)!种排列。
所以你就可以看成是按照每组(n-1)!个这样分组。
利用 k/(n-1)! 可以取得最高位在数列中的index。这样第k个排列的最高位就能从数列中的index位取得,此时还要把这个数从数列中删除。
然后,新的k就可以有k%(n-1)!获得。循环n次即可。
class Solution {
public:
string getPermutation(int n, int k) {
string ret;
vector<int> factorial(n,1); #计算阶乘
vector<char> num(n,1);
for(int i=1; i<n; i++)
factorial[i] = factorial[i-1]*i;
for(int i=0; i<n; i++)
num[i] = (i+1)+'0';
k--;
for(int i=n; i>=1; i--) {
int j = k/factorial[i-1];
k %= factorial[i-1];
ret.push_back(num[j]);
num.erase(num.begin()+j); //删除第j个元素,同时调整元素排序关系
}
return ret;
}
};