dfs 全排列 使用交换——含重复元素和非重复元素

15. 全排列

中文
English

给定一个数字列表,返回其所有可能的排列。

样例

样例 1:

输入:[1]
输出:
[
  [1]
]

样例 2:

输入:[1,2,3]
输出:
[
  [1,2,3],
  [1,3,2],
  [2,1,3],
  [2,3,1],
  [3,1,2],
  [3,2,1]
]

挑战

使用递归和非递归分别解决。

注意事项

你可以假设没有重复数字。

(A、B、C、D)的全排列为

1、A后面跟(B、C、D)的全排列

2、B后面跟(A、C、D)的全排列(A与B交换,其他次序保持不变)

3、C后面跟(B、A、D)的全排列(A与C交换,其他次序保持不变)

4、D后面跟(B、C、A)的全排列(A与D交换,其他次序保持不变)

 

举例说明,【1,2,3】:

                  root

              /      |    \

           1        2       3

        /  \       / \      / \

       2    3    1    3    1   2

      /       \   ...         ....

    3         2

也就是说:permutate([1,2,3]) = {[1]+permutate([2,3]),  [2]+permutate([1,3]), [3]+permutate([1,2])}

使用交换思路后编码如下:

class Solution:
    """
    @param: :  A list of integers
    @return: A list of unique permutations
    """

    def permute(self, nums):
        # write your code here
        result = []
        self.find_permutations(nums, 0, result)
        return result


    def find_permutations(self, nums, start_index, result):
        if start_index >= len(nums):
            result.append(list(nums))
            return

        for i in range(start_index, len(nums)):
            nums[start_index], nums[i] = nums[i], nums[start_index]
            self.find_permutations(nums, start_index + 1, result)
            nums[start_index], nums[i] = nums[i], nums[start_index]

 

 

含有重复元素的全排列:

举例说明,【1,1,2】:

                    root

              /        |          \

           1         1(重复)       2

        /  \       / \             / \

       1    2     2    1          1    1(重复)

      /       \    |     |          |     |

    2         1    1    2         1    1

 

 

再举例说明,【1,2,2】:

 

                           root

 

              /               |          \

 

           1                 2              2(重复)

 

        /  \               / \             / \

 

       2    2(重复)2    1         1     2   

 

      /       \           |     |          |     |

 

    2         2          1    2         2    1

 


 

代码如下:就是用比较无脑的交换做法,当前交换的元素nums[i], 只要在nums[start_index:i]有重复元素存在就说明之前的路径已经走过。

class Solution:
    """
    @param: :  A list of integers
    @return: A list of unique permutations
    """

    def permuteUnique(self, nums):
        # write your code here
        result = []
        self.find_permutations(nums, 0, result)
        return result

    def find_permutations(self, nums, start_index, result):
        if start_index >= len(nums):
            result.append(list(nums))
            return

        for i in range(start_index, len(nums)):
            if nums[i] in nums[start_index:i]:
                continue
            
            nums[start_index], nums[i] = nums[i], nums[start_index]
            self.find_permutations(nums, start_index + 1, result)
            nums[start_index], nums[i] = nums[i], nums[start_index]

 

 和不重复元素的全排列算法比较看来,无非就是多了一个swap的判断。

 

10. 字符串的不同排列

中文
English

给出一个字符串,找到它的所有排列,注意同一个字符串不要打印两次。

样例

样例 1:

输入:"abb"
输出:
["abb", "bab", "bba"]

样例 2:

输入:"aabb"
输出:
["aabb", "abab", "baba", "bbaa", "abba", "baab"]
class Solution:
    """
    @param str: A string
    @return: all permutations
    """
    def stringPermutation2(self, str):
        # write your code here
        self.result = []
        self.dfs(s=list(str), start_index=0)
        return ["".join(w) for w in self.result]
        
    
    def dfs(self, s, start_index):
        if start_index == len(s):
            self.result.append(s[:])
            return
        
        for i in range(start_index, len(s)):
            if s[i] in s[start_index:i]:
                continue
            
            s[start_index], s[i] = s[i], s[start_index]
            self.dfs(s, start_index+1)
            s[start_index], s[i] = s[i], s[start_index]
            

 

 

posted @ 2019-10-13 22:09  bonelee  阅读(587)  评论(0编辑  收藏  举报