leetcode 关于全排列题目的简单总结
来源:互联网 发布:大数据在医疗领域应用 编辑:程序博客网 时间:2024/05/17 10:53
266Palindrome Permutation 52.6% Easy 46Permutations37.7% Medium 267Palindrome Permutation II 29.5% Medium 47Permutations II29.3% Medium 31Next Permutation 27.3%Medium 60Permutation Sequence 26.0% Mediumleetcode上一共六道涉及到全排列的问题,这里简单的总结一下:
第一 如何求一个字符串的全排列
求全排列比较常见的是两种方法,一种是递归,一种是字典序的方法,递归思想是这样的,我们试想一个简单的例子,123的全排列:
123
132
213
231
312
321
我们可以理解为分别将长度为n的数组的每一个数与数组的第一个数进行交换,然后对后面的n-1子数组进行全排列,这样得到的代码也比较简洁:
public void arrange (String[] str, int st, int len){ if (st == len - 1) { for (int i = 0; i < len; i ++) { System.out.print(str[i]+ " "); } System.out.println(); } else { for (int i = st; i < len; i ++) { swap(str, st, i); arrange(str, st + 1, len); swap(str, st, i); } }}字典序是指将一个字符串以字典序升序的方式排列,再如上例的123,当按照一定的交换规则变成321,即不存在升序的时候表示排列完成,字典序的全排列生成是有严格顺序的,c++中有next_permutation函数来生成一个排列的下一个字典序排列,字典序的生成规则如下:
一般而言,设P是[1,n]的一个全排列。 P=P1P2…Pn=P1P2…Pj-1PjPj+1…Pk-1PkPk+1…Pn find: j=max{i|Pi<Pi+1}
k=max{i|Pi>Pj} 1, 对换Pj,Pk,
2, 将Pj+1…Pk-1PjPk+1…Pn翻转
P’= P1P2…Pj-1PkPn…Pk+1PjPk-1…Pj+1即P的下一个
【例】 如何得到346987521的下一个 1,从尾部往前找第一个P(i-1) < P(i)的位置 3 4 6 <- 9 <- 8 <- 7 <- 5 <- 2 <- 1 最终找到6是第一个变小的数字,记录下6的位置i-1 2,从i位置往后找到最后一个大于6的数 3 4 6 -> 9 -> 8 -> 7 5 2 1 最终找到7的位置,记录位置为m 3,交换位置i-1和m的值 3 4 7 9 8 6 5 2 1 4,倒序i位置后的所有数据 3 4 7 1 2 5 6 8 9 则347125689为346987521的下一个排列next_permutation java代码:
public void nextPermutation(int[] num) { //1.找到最后一个升序位置pos int pos = -1; for (int i = num.length - 1; i > 0; i--) { if (num[i] > num[i - 1]) { pos = i - 1; break; } } //2.如果不存在升序,即这个数是最大的,那么反排这个数组 if (pos < 0) { reverse(num, 0, num.length - 1); return; } //3.存在升序,那么找到pos之后最后一个比它大的位置 for (int i = num.length - 1; i > pos; i--) { if (num[i] > num[pos]) { int tmp = num[i]; num[i] = num[pos]; num[pos] = tmp; break; } } //4.反排pos之后的数 reverse(num, pos + 1, num.length - 1);}public void reverse(int[] num, int begin, int end) { int l = begin, r = end; while (l < r) { int tmp = num[l]; num[l] = num[r]; num[r] = tmp; l++; r--; }}代码是leetcode next permutation的ac代码,按照要求当字符串是完全降序的时候倒序字符串,整个过程就是next_permutation的思想。
下面来看一下palindrome permutationII和permutation sequence两道题:
Given a string s
, return all the palindromic permutations (without duplicates) of it. Return an empty list if no palindromic permutation could be form.
For example:
Given s = "aabb"
, return ["abba", "baab"]
.
Given s = "abc"
, return []
.
Hint:
- If a palindromic permutation exists, we just need to generate the first half of the string.
- To generate all distinct permutations of a (half of) string, use a similar approach from: Permutations II or Next Permutation.
第一,生成回文全排列,我们只需要生成前半部分,然后倒转生成后半部分即可;
第二,生成全排列的方法,这个生成方法有很多,记得需要考虑重复元素的问题;
需要注意的地方有:
1)回文只允许至多一个奇数次的字符,若多于一个必定无法构成回文。
2)奇数长度和偶数长度如何处理
这里引用https://discuss.leetcode.com/topic/22214/ac-java-solution-with-explanation的代码,清晰明了:
public List<String> generatePalindromes(String s) { int odd=0; List<String> list=new ArrayList<>(); Map<Character,Integer> map=new HashMap<>(); for(int i=0;i<s.length();i++){ char temp=s.charAt(i); map.put(temp,map.containsKey(temp)?map.get(temp)+1:1); odd+=map.get(temp)%2==1?1:-1; } String str=""; List<Character> charlist=new ArrayList<>(); if(odd>1) return list; for(Character key:map.keySet()){ if(map.get(key)%2==1) str+=key; int val=map.get(key); for(int i=0;i<val/2;i++){ charlist.add(key); } } getPumu(list,charlist,new StringBuilder(),new boolean[charlist.size()],str); return list;}public void getPumu(List<String> list,List<Character> charlist,StringBuilder sb,boolean[] used,String str){ if(sb.length()==charlist.size()){ list.add(sb.toString()+str+sb.reverse().toString()); sb.reverse(); return; } for(int i=0;i<charlist.size();i++){ if(i>0&&charlist.get(i)==charlist.get(i-1)&&!used[i-1]) continue; if(!used[i]){ used[i]=true; sb.append(charlist.get(i)); getPumu(list,charlist,sb,used,str); used[i]=false; sb.deleteCharAt(sb.length()-1); } }}
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.
当然可以用next_pumutaion多次调用,但是细心观察显然是有数学规律的,显然1-n的全排列有n!种排列,而以1、2、3......n为开头的排列各有(n-1)!种排列,那么所求p=k/(n-1)!的nums[p]即为该排列的第一个数字,依次类推可以求出该排列的所有数字,代码:public String getPermutation(int n, int k) { List list=new ArrayList<>(); int multiply=1; for(int i=0;i<n;i++){ list.add(i+1); multiply*=i+1; } String res=""; for(int i=0;i<n;i++){ multiply=multiply/(n-i); int index=multiply/k; res+=list.get(index); list.remove(index); k=multiply%k; } return res;}
- leetcode 关于全排列题目的简单总结
- 关于全排列的总结
- 关于全排列 leetcode
- 全排列的题目
- 简单的全排列
- 关于全排列问题的总结(康托展开)
- leetcode总结 -- 关于tree path的题目
- 全排列的简单实现
- 一个简单的全排列
- 全排列的一些总结
- leetcode题目 全排列(三种解法)
- 题目1120:全排列
- 题目1120:全排列
- 题目:全排列
- 题目1120:全排列
- 题目1120:全排列
- 题目1120:全排列
- LeetCode(Permutations) 数列的全排列
- 《剑指offer》42:翻转单词顺序
- spring中ApplicationContextAware接口
- 湖南省第七届省赛 打怪升级
- 使用SPARK 对支付系统进行并发交易笔数统计
- js课程笔记(一)前五节课基础内容总结
- leetcode 关于全排列题目的简单总结
- 一个很简单的demo来演示一个账号只能同时被一个人使用(Java实现)
- Android/Java面试题收集
- Maven学习 (五) Elipse中发布一个Maven项目到Tomcat
- 如何看原理图?
- 实例解析Docker数据卷+数据卷容器+flocker数据共享+DockerHub操作
- JQuery小知识总结
- 【树10】对称二叉树
- 程序员解决问题的60个策略