LeetCode:46 全排列(Golang)

题目描述

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

示例 1:
输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

分析

与组合问题一样,排列问题同样可以看作是一棵树,于是就有DFS遍历;显然也要用递归算法。具体思路是让数组中的元素"轮流当老大":
1.每次递归,只需要把轮到的元素放到第一位(该元素当老大);
2.排列的结果是老大+所有小弟的全排列;
3.对于同一层:由于老大是不同的,因此排列结果不会有重复;
4.对于下一层:老大坐稳后,第二个位置就变成新的老大;小弟们再次轮流选坐;

代码版本一

按照最直观的思路,每一层把老大推进"排位切片permu",剩下的小弟传入下一层迭代;

func permute(nums []int) (res [][]int) {
   dfs := func([]int, []int) {}
   dfs = func(nums []int, permu []int) { // permu为排位切片
      if len(nums) == 0 {
         res = append(res, append([]int{}, permu...))
         return
      }
      for i, num := range nums {
         permu = append(permu, num)
         dfs(append(append([]int{}, nums[:i]...), nums[i+1:]...), permu)
         permu = permu[:len(permu)-1]
      }
   }
   dfs(nums, []int{})
   return
}

时间复杂度 O(n!);

代码版本二

版本一的每一层dfs函数都要为其局部变量 nums 和 permu 开辟内存;空间复杂度较高。
其实轮流当老大只需要把元素位置跟第一位的元素交换即可;因为当前层级只关心谁是老大,不用关心其余小弟们的顺序。同时我们也不需要另外一个排列切片permu,整个递归过程都在nums上进行;

func permute(nums []int) (res [][]int) {
   dfs := func(int) {}
   n := len(nums)
   dfs = func(idx int) { // idx 代表排第几位
      if idx == n {
         res = append(res, append([]int(nil), nums...))
         return
      }
      for i := idx; i < n; i++ { // 本层轮流当老大
         nums[i], nums[idx] = nums[idx], nums[i]
         dfs(idx + 1)
         nums[i], nums[idx] = nums[idx], nums[i]
      }
   }
   dfs(0)
   return
}

在每一次完全排列完之后,代码还会进入下一层循环以判断边界(即是否到达n),复杂度变为了 O(n*n!) ;
但空间复杂度大大降低了,因此运行效率可能会更高。

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值