leetcode_全排列—回溯法、深度优先搜索

描述:

给定一个 没有重复 数字的序列,返回其所有可能的全排列。

示例:

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

解题思路:

方法1:回溯法

回溯法的原理在于在前n-1位元素确定的情况下,求取n位以后的全排列。以1,2,3为例,首先固定第0位,就是分别将第0位与它本身及后面各位元素交换,得到3种不同的可能,在固定这一位后,在考虑第1位的可能性,将第1位与它本身及其后元素交换,有两种可能性,当前两位元素确定后,最后一位只有一种可能性。因此一共有6种可能。

def permute(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        def backtrack(pos,end):
            if pos == end:
                res.append(nums[:])
                return

            for i in range(pos, end):
                nums[i], nums[pos] = nums[pos], nums[i]
                backtrack(pos + 1, end)
                nums[i], nums[pos] = nums[pos], nums[i]

        res = []
        backtrack(0, len(nums))
        return res

方法2:深度优先搜索

  推荐啊哈!算法这本算法书,比较直观易理解

(个人理解以及结合啊哈算法中的理解):这题可以简单理解为有n位数字序列,放在n个位置,有多少种放置方案。

以1、2、3为例,对应1,2,3三个位置

实际模拟执行放置:

1、对于第一个位置可以放置1,按照递增的顺序放置数字

2、第2个位置可以放置2,第3个位置可以放置3,产生序列1,2,3

3、接着对于第3个位置,尝试新的放置可能,没有可放置的数字。于是将2号位置的数字回收

4、在第二个位置放置数字3,于是第三个位置此时只能放置2。产生另一序列1,3,2

5、重复以上行为可以得到全排列

从代码层面理解:

每个位置放置所有可能的数字

for i in range(0,len(nums)):
    tmp[step] = nums[i]

其中tmp是一个临时数组,对于第step位置,放置第i个数。现在我们考虑另一个问题,对于第i 个数放在了第step的位置,那么就不能放在其他位置了。因此需要一个book数组标记哪些数字已经被放置了。

for i in range(0,len(nums)):
    if book[i]:
        tmp[step] = nums[i]
        book[i] = False

对于第step的位置处理完了,需要考虑step+1的位置。第step+1的位置和step的操作完全相同,因此可以进行封装。其实这里就是一个套娃,会一直嵌套处理step+1的相对下一个位置step+1+1,一直嵌套下去,处理后续位置的数据。

按照实际模拟执行放置:第3步,执行完一趟之后,需要将数字进行回收,才能进行下一趟的操作。

 for i in range(0,len(nums)):
     if book[i]:
         tmp[step] = nums[i]
         book[i] = False
         dfs(step+1)
         book[i] = True

最后需要考虑的是,什么时候得到一个满足条件的序列,即终止条件。当处理完第n个位置的时候,就得到一个满足要求的序列。

class Solution(object):
    def permute(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        book = [True for _ in range(len(nums))]
        tmp = [i for i in range(len(nums))]

        def dfs(step):
            if step == len(nums):
                res.append(tmp[:])
                return

            for i in range(0,len(nums)):
                if book[i]:
                    tmp[step] = nums[i]
                    book[i] = False
                    dfs(step+1)
                    book[i] = True

        res = []
        dfs(0)
        return res    

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值