本文解说4道关于permutation的题目:

1. Permutation:输出permutation——基础递归 
2. Permutation Sequence: 输出字典序排列的第k个permutation——推理
3. Next Permutation:给定一个permutation中的序列,求字典序它的下一个permutation是什么——逻辑推理
4. Permutation II:和第一题有细微的区别: 对于一个可能有反复元素的数组输出全部permutation——有条件dfs

                                                                                             

1. Permutation:输出permutation

——基础递归

 class Solution{
private:
vector<vector<int> > L;
vector<int> Nums;
int l;
vector<bool> visited;
public:
void perm(vector<int>& list){
if(list.size()==l){
L.push_back(list);
return;
}
for(int i=0; i<l; i++){
if(!visited[i]){
list.push_back(Nums[i]);
visited[i] = true;
perm(list);
list.pop_back();
visited[i] = false;
}
}
} vector<vector<int> > permute(vector<int> &num){
int i;
Nums = num;
l = Nums.size();
for(i=0;i<l;i++)
visited.push_back(false);
vector<int>list;
perm(list); //for(i=0;i<L.size();i++){
// for(int j = 0;j<l;j++)
// cout<<L[i][j];
// cout<<endl;
//}
return L;
}
};

                                                                                             

2. Permutation Sequence: 输出字典序排列的第k个permutation

——逻辑推理

酱想。n位的permutation有n!个。那么第k个permutation假设满足n!<k<(n+1)!就一定有,

a = k/n!

b = k%n!

取集合里的第a位做下一位。下一次分析剩下的字符组成的第b个permutation

------------------------

e.g. 求[1,2,3,4]组合的第10个

①求[1,2,3,4]组合的第10个

10/3! = 1…4 --->找到[1,2,3,4]中第(1+1)个数(2)做下一位,留下[1,3,4]

②求[1,3, 4]组合的第10-3! * 1 = 4个

4/2! = 2…0 --->找到[1,3,4]中第2个数(3)做下一位, 留下[1,4]

③余零。说明是permutation里的最后一个 -> 剩下的逆序输出

--->2341

class Solution {
public:
string getPermutation(int n, int k) {
int i,j,sum = 1;
//sum = (n-1)!
for (i=2; i<n; i++) {
sum *= i;
}
bool visited[n+2];
memset(visited, false, sizeof(visited));
string str;
for(i=1;i<n;i++){
int nextidx = k/sum;
k = k%sum;
if(k==0)
nextidx -- ;
sum/=(n-i);
int cnt = 0;
for (j=0; j<n; j++) {
if (!visited[j]) {
if (cnt == nextidx){
visited[j] = true;
str += '0' +j+1;
break;
}
cnt ++;
}
}
}
for(j=n-1;j>=0;j--){
if (!visited[j]) {
str += '0' + j+1;
}
}
return str; }
};
                                                                                             

3. Next Permutation

给定一个permutation中的序列,求字典序它的下一个permutation是什么。

——逻辑推理

能够发现,下一个permutation能够这么得来:

①当前permutation从后往前找到一直上升的子序列,假如一直上升到index_i

②找到index为i到end中最小的。比num[i-1]大的数字,记index为j。交换num[i-1],num[j]

③对num[i]~num[end]从小到大排序

PS:要注意有反复元素的情况e.g {1,5,1};

code:

class Solution {
public:
void nextPermutation(vector<int> &num) {
size_t n = num.size();
int i = (int)n-1;
int j=0;//find the position that stops increasing from tail
while(num[i]<=num[i-1] && i>0)
i--; sort(num.begin()+i, num.end());
//find the digit that substitute(swap with) i
for(j=i;j<n;j++){
if (num[j]>num[i-1]) {
break;
}
}
if(i>0 && j<n)
swap(num[i-1], num[j]);
}
};
                                                                                             


4. Permutation II

和第一题有细微的区别: 对于一个可能有反复元素的数组输出全部permutation。

——有条件dfs

想一下递归条件:

肯定还是递归,递归条件应该是假设当前list中已经出现过这几个元素排列。就不要再加进去。

所以在第一题基础上仅仅加两点:

1)对数组里全部元素排序

2)对于上一次加到过list的同样元素(必定是在排序后数组中与上一个相邻元素同样的)不要再加

class Solution{
private:
vector<vector<int> > L;
vector<int> Nums;
int l;
vector<bool> visited;
public:
void perm(vector<int>& list){
if(list.size()==l){
L.push_back(list);
return;
}
for(int i=0; i<l; i++){
if(!visited[i]){
list.push_back(Nums[i]);
visited[i] = true;
perm(list);
list.pop_back();
visited[i] = false; while (i<l && Nums[i+1]==Nums[i]) {
i++;
}
}
}
} vector<vector<int> > permuteUnique(vector<int> &num){
int i;
Nums = num;
l = Nums.size();
sort(Nums.begin(),Nums.end());
for(i=0;i<l;i++)
visited.push_back(false);
vector<int>list;
perm(list); return L;
}
};

排列组合(permutation)系列解题报告的更多相关文章

  1. LeetCode: Permutation Sequence 解题报告

    Permutation Sequence https://oj.leetcode.com/problems/permutation-sequence/ The set [1,2,3,…,n] cont ...

  2. 【LeetCode】60. Permutation Sequence 解题报告(Python & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 日期 题目地址:https://leetcode.c ...

  3. SPOJ QTREE 系列解题报告

    题目一 : SPOJ 375 Query On a Tree http://www.spoj.com/problems/QTREE/ 给一个树,求a,b路径上最大边权,或者修改a,b边权为t. #in ...

  4. 自然语言处理(NLP) - 数学基础(1) - 排列组合

    正如我在<自然语言处理(NLP) - 数学基础(1) - 总述>一文中所提到的NLP所关联的概率论(Probability Theory)知识点是如此的多, 饭只能一口一口地吃了, 我们先 ...

  5. 【LeetCode】266. Palindrome Permutation 解题报告(C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 字典 日期 题目地址:https://leetcode ...

  6. 【剑指Offer】字符串的排列 解题报告(Python)

    [剑指Offer]字符串的排列 解题报告(Python) 标签(空格分隔): LeetCode 题目地址:https://www.nowcoder.com/ta/coding-interviews 题 ...

  7. LeetCode解题报告—— Jump Game & Merge Intervals & Permutation Sequence

    1. Jump Game Given an array of non-negative integers, you are initially positioned at the first inde ...

  8. 【九度OJ】题目1072:有多少不同的面值组合? 解题报告

    [九度OJ]题目1072:有多少不同的面值组合? 解题报告 标签(空格分隔): 九度OJ http://ac.jobdu.com/problem.php?pid=1072 题目描述: 某人有8角的邮票 ...

  9. 【排列组合】ZSC1076: 数学、不容易系列之三——考新郎

    国庆期间,省城刚刚举行了一场盛大的集体婚礼,为了使婚礼进行的丰富一些,司仪临时想出了有一个有意思的节目,叫做"考新郎",具体的操作是这样的: 首先,给每位新娘打扮得几乎一模一样,并 ...

随机推荐

  1. 迅为嵌入式4418/6818开发板QT-HDMI显示

    本文转自迅为论坛:http://www.topeetboard.com 平台:迅为4418/6818开发平台 1.首先请确认下光盘资料的日期(只有20171120及以后更新的光盘支持QT HDMI显示 ...

  2. Vuex的全面用法总结

    1. vuex简介 vuex是专门用来管理vue.js应用程序中状态的一个插件.他的作用是将应用中的所有状态都放在一起,集中式来管理.需要声明的是,这里所说的状态指的是vue组件中data里面的属性. ...

  3. Jmeter之WebService接口测试

    一.简介  1.JMeter3.2前的版本,可以使用SOAP/XML-RPC Request插件直接进行webservice接口,而3.2后的版本则已经取消了这个接口,需要另外的方法才能进行测试. 2 ...

  4. Js 之图片懒加载插件

    一.PC端(lazyload) 1.引入js文件 <script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.m ...

  5. Spring MVC全局异常后返回JSON异常数据

    问题: 当前项目是作为手机APP后台支持,使用spring mvc + mybaits + shiro进行开发.后台服务与手机端交互是发送JSON数据.如果后台发生异常,会直接返回异常页面,显示异常内 ...

  6. 第2节 hive基本操作:6、7、8

    第1节 hive安装:6.hive的基本操作:7.创建数据库的语法:8.hive当中创建内部表的语法. hive的基本操作: 创建数据库与创建数据库表操作 创建数据库操作:create databas ...

  7. python 弹窗

    import ctypes message = ctypes.windll.user32.MessageBoxA(0,'message','tips',0)

  8. windows系统查看目录树

    进入到需要查看的目录后,按住shift键,然后单击鼠标右键,选择“在此处打开命令窗口”,然后命令行窗口界面. 1.若是只查看该目录下有哪些目录,输入tree即可 2.若是显示该目录及其子目录下的所有目 ...

  9. js 技巧 (一)

      · 事件源对象 event.srcElement.tagName event.srcElement.type · 捕获释放event.srcElement.setCapture();  event ...

  10. linux下的文档处理及tar命令

    1.使用cat命令进行纵向合并 使用‘>’是将左边的内容覆盖到右边 使用‘>>’是将左边的内容追加到右边文档中 还可使用‘>’将不同文件进行合并 2.管道符‘|’统计行数 使用 ...