目录
0.简介
最近参加了网易校招的提前批笔试,其中有一题是关于字典排序问题:
问题说明:
假设给定m个'a'和n个'z',求按照字典排序生成的第k个字符串(字符串长度为m+n,无重复序列)
本人以前在LeetCode上刷了大约100道题,其中也遇到了一些关于字典排序的问题,不过上面这个题实在是不会做,如果有哪位大神知道解,还请不吝赐教。
本博文整理了我在LeetCode上遇到的字典排序(即排列)问题,题目链接如下,本文所给出的解法参考了LeetCode上大神的答案,本文所有代码均为python3:
1.无重复数字的排列:Permutations
2.有重复数字的排列:Permutations II
3.第k个排列:Permutation Sequence
1.无重复数字的排列
问题说明:
给定一组不同的整数,返回所有可能的排列。
例如:
Input: [1,2,3] Output: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ]
方法一:
采用深度优先搜索,比较好理解,每次按顺序从剩余序列中选择一个数插入到path中,直到访问完所有点。
class Solution:
def permute(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
res = []
def dfs(A, path, res):
if not A:
res.append(path)
for i in range(len(A)):
dfs(A[:i]+A[i+1:], path+[A[i]], res)
dfs(nums, [], res)
return res
方法二:
这是LeetCode上一位非常非常牛逼的人的答案,很多题目下都有这位StefanPochmann大神完美解答,有兴趣可以去围观。
这个方法其实和方法一的思路是一样的,在此列出来是因为本人很羡慕这种一句话解决的代码。
class Solution:
def permute(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
return [[n]+p
for i, n in enumerate(nums)
for p in self.permute(nums[:i]+nums[i+1:])] or [[]]
2.有重复数字的排列
问题说明:
给定可能包含重复项的数字集合,返回所有可能的唯一排列。
例如:
Input: [1,1,2] Output: [ [1,1,2], [1,2,1], [2,1,1] ]
思路:
采用插入法:
第一步,把第一个数插入到空列表[]中,res = [[1]];
第二步,此时的num还是1,这是ans = [1],虽然有前后两个位置可以插入,但是为了排除重复,只往相同数字的前方各位置插入,此时的res = [[1, 1]];
第三步,此时的num为2,ans = [1, 1],此时ans中没有等于2的数字,因此2就可以插入到ans的len(ans)+1个位置,分别产生[2,1,1],[1,2,1],[1,1,2];
到此所有数字处理完毕,res = [[2,1,1], [1,2,1], [1,1,2]],由于结果需要按字典序列输出,那么排序以下就好了。
class Solution:
def permuteUnique(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
# 插入法
res = [[]]
for num in nums:
new_res = []
for ans in res:
# 长度为len(ans)的序列有len(ans)+1个插入点
for i in range(len(ans)+1):
new_res.append(l[:i]+[num]+l[i:])
# 遇到相同的数,只往前插,不往后插
if i<len(l) and l[i]==num:
break #handles duplication
res = new_res
return list(sorted(res))
3.第k个排列
问题说明:
集合[1,2,3,...,n]总共包含n!独特的排列。
通过按顺序列出和标记所有排列,我们得到n = 3的以下序列:
"123"
"132"
"213"
"231"
"312"
"321"
给定n和k,返回第k个排列序列。
注意:
给定n将介于1和9之间。
给定k将介于1和n!之间。Example 1:
Input: n = 3, k = 3 Output: "213"
Example 2:
Input: n = 4, k = 9 Output: "2314"
思路:
对于n的排列,第一个(n-1)! 排列从1开始,下一个(n-1)! 从2开始,......等等。 并且在每组(n-1)中! 排列,第一个(n-2)! 排列从最小的剩余数字开始,......
因此,我们可以使用循环来检查序列号落入的区域并获得起始数字。 然后我们调整序列号并继续。
class Solution:
def getPermutation(self, n, k):
"""
:type n: int
:type k: int
:rtype: str
"""
import math
ans = ""
a = list(range(1, n+1))
k -= 1 # 消除index==0的影响
while n > 0:
n -= 1
# 获取序号
index, k = divmod(k, math.factorial(n))
ans += str(a[index])
# 删除使用过的数字
a.remove(a[index])
return ans
目前遇到的关于排列的问题就是上面这些,如果以后有遇到会更新本文。
--by 2018/8/22