Permutation递归解法

来源:互联网 发布:数据可视化公司招聘 编辑:程序博客网 时间:2024/06/10 04:00

https://leetcode.com/problems/permutations/

https://leetcode.com/problems/permutations-ii/

permutation的题一般来说是给一个序列,然后要求得到所有的不同permutation。对于这类题需要分下面这几种情况

1. 从input的内容来分:有2种,分别是有duplicate和no duplicate的

解法:这两种情况的结果其实有有同一个特性:在同一个position,同一种字母只能出现一次。只不过没有duplicate的情况下不需要额外处理就可以达到这个效果。针对有duplicate的情况,我们在每次的recursion中都需要设置一个set来储存这个位置已经使用过的数字或者字母。见如下的tree:

example: input is: 1, 1, 2
on each recursion level, we skip the duplicate number                /       |      \               1       [1]重复  2               n             /  \     / \      |  \            1    2   1   2     1  [1]重复       n * (n - 1)           /    /   /   /      |   |          2    1   2   1       1   1            n * (n - 1) * (n - 2)time: O(n!)space: O(n)1 1 21 2 12 1 1

2. 从input的type来分:

1. 可以是array

2. 可以是list

3. 也可以是个string

区别:这里的区别在于是否能够in place操作其中的element。比如array就可以快速的swap里面的element,这时候我们的permutation就可以使用swap的方式。但是string是没有办法这样操作的。所以如果后面2种情况出现又想要做in place的话,最好是重新建立一个array来储存其中的内容。这样也可以避免List的get()的时间复杂度不恒定的问题。string可以使用toCharArray()来得到char的array

3. 从output的要求来分:

1是不用output,就print出来。

2是要返回一个List<string>。

3是要返回一个List<List<Integer>>

区别: 1.如果不用output,我们可以写一个函数把那个array或者temp arraylist中的内容打印出来。这个问题一般不大

2. 如果需要返回一个string,那么input一般来说是一个string或者是char array.这类的做法也比较方便,用swap的方法最后rst.add(new String(input))就可以实现

3. 需要注意的是如果要求返回的值是List<List<Integer>>,那么最后加入rst的那步一定是需要一个一个把array中的数字添加到最后的list中去的。最好是这样做,可以保证不会出问题。因为并不是很麻烦而且不会出现想用现成函数用错的情况。毕竟list中的是object而array中的可能是permitIve type


https://leetcode.com/problems/next-permutation/

这题虽然也有permutation,实际上和permutation关系不大。让求得是lexicographically next greater permutation of numbers. lexicographically大的意思就是说对这个数字的所有permutations进行从小到大额排序后随便抽一个出来问这个的下一个是什么。比如说:123的排序有:

123,132, 312, 321, 213, 231

对这些数字进行排序之后得到:123, 132, 213, 231, 312, 321

问132的下一个lexicographically大的数字是哪个?答案是213

所以我们可以看到光问下一个是什么,我们可以把所有的permutation都解出来,然后排序,然后找到下一个是什么。但是这样操作的话时间复杂度太高。所以我们还是得另辟蹊径。对数字进行观察可以发现,我们想要做得是尽量让这个数字而的右边的位数变大的同时也能让整个数字的大小变大。我们的做法是把digits分成2块。每次看一个位数1【3】2。假如3需要被置换掉的话,我们只在3的右边看能不能找到数字让它变大。如果能够的话,就保证了左边那块权重更重的不会受到影响。所以针对132

先看3, 发现右边的2只能把它变小,不行。continue

再看1,发现右边可以找到数字让它变大,那么找到右边比1大的最小的数字2, 然后进行置换得到213,后面还要进行的一个操作是把后【13】进行从小到大的排序,使得右边的的确是能得到的最小的数。通过这样的过程,我们保证了尽量使得数字变大的同时让其变大的幅度最小。

0 0