全排列

76 阅读3分钟

给定一个不含重复数字的数组 nums ,返回其所有可能的全排列。你可以按任意顺序返回答案。

回溯法学习

采用深度优先搜索的思想。这个算法能通过尽可能深的方式探索搜索树或者图,进而遍历所有的可能性。该算法采用循环+递归+回撤的方式实现。

个人理解
  1. 怎么遍历? 从空节点开始,先定排列中第一个元素,也就是循环遍历所有元素(for循环实现),然后进入访问的第二个元素进行同样的操作。

  2. 怎么保证不重复访问同一节点?
    为每个节点设置访问状态。访问了就修改状态,修改后递归访问第二个节点。

  3. 怎么实现/回到过去?
    修改访问状态+还原进行了的一切操作,这是在递归访问后进行。还原后for循环进行第二个元素的操作,也就是本层搜索树开始进行第二种情况的探索了(相当于平行宇宙)。

写代码bug

pyhon存储列表的时候,是存储列表指针的,而不是列表数据,后面改变了指针的值,会改变所有的,在回溯回起始状态时,指针会变为空,所以result加路径时,要存储列表的副本,可以采用my[:]或者list(my)来实现。

自己的写法
class Solution(object):
    def permute(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        length = len(nums)
        flag = [0] * length
        result = list()
        def dfs(height):
            if height == length:
                #保存每个结果,注意这里是要保存当前my的副本,my是一个引用,后面会修改
                result.append(my[:])
                return
            #遍历每种情况
            for i in range(length):
                if flag[i] == 0:
                    my.append(nums[i])
                    flag[i] = 1
                    dfs(height+1)
                    #回撤操作,将原来修改了的变量都取消
                    flag[i] = 0
                    my.pop()
        my = list()#路径
        dfs(0)
        return result
改进

在遍历每种情况的时候,每次都对所有元素进行判断有无访问过,使用这种方式有很多重复的操作,那么怎么将未访问过的元素集中起来呢?这样可以除去判断操作。

看题解后,让我想起了类似于排序算法时处理未排序数字的方式,将使用过的元素换到左边,未排序的放到右边。

为什么第一个if后不用return
因为range(length,length)相当于是空操作,height前都是索引过的值,height后都是待定索引。

class Solution(object):
    def permute(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        length = len(nums)
        flag = [0] * length
        result = list()
        def dfs1(height):
            if height == length:
                #保存每个结果
                result.append(nums[:])
                #此处可以不用return,因为range(length,length)相当于是空操作
            #height前都是索引过的值,height后都是待定索引
            for i in range(height,length):
                #交换一次,表示这次选择nums[i]
                ums[i],nums[height] = nums[height],nums[i]
                #下一层
                dfs1(height+1)
                #撤销原来的操作
                nums[i],nums[height] = nums[height],nums[i]
        dfs1(0)
        return result