算法训练 Day 29

LeetCode 491. 递增子序列

题目链接:491. 递增子序列

思路:此题与90. 子集 II有些类似,都可能包含重复元素。但其实有着本质的区别,我们在做子集问题的时候为了去重的简便而对数组进行了排序,但很显然,此题万万不可用排序,题目就是要求我们找其中的递增子序列的。所以为了进行去重的操作,我们需要采用一种新的方法, 比如哈希表或者集合。

Python版本:

class Solution:
    def findSubsequences(self, nums: List[int]) -> List[List[int]]:

        def backtrack(start, path):
            if len(path)>1:
                res.append(path[:])

            hashset = set()
            for i in range(start, len(nums)):
                if (len(path)>0 and nums[i]<path[-1]) or nums[i] in hashset:
                    continue

                hashset.add(nums[i])
                path.append(nums[i])
                backtrack(i+1, path)
                path.pop()

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

go版本:

var res [][]int

func findSubsequences(nums []int) [][]int {
    res = [][]int{}
    path := []int{}
    backtrack(0, path, nums)
    return res
}

func backtrack(start int, path, nums []int) {
    if len(path)>1 {
        tmp := make([]int, len(path))
        copy(tmp, path)
        res = append(res, tmp)
    }

    set := [201]int{}
    for i:=start; i<len(nums); i++ {
        if (len(path)>0 && nums[i]<path[len(path)-1]) || set[nums[i]+100]==1 {
            continue
        }
        set[nums[i]+100] = 1
        path = append(path, nums[i])
        backtrack(i+1, path, nums)
        path = path[:len(path)-1]
    }
}

因为go没有set这种数据结构,又因为题目给定 -100<nums[i]<100,所以创建一个长度大于200的哈希表来代替。

LeetCode 46. 全排列

题目链接:46. 全排列

思路:可以与组合问题进行类比。全排列也是使用基本的回溯步骤,但与组合问题最大的区别在于start(每一次向深度搜索的起始值)的设置,因为全排列每次都需要将所有数组排列进去,所以在每次循环的时候都需要遍历整个数组,而不是range(start, len(nums))。

Python版本:

class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:

        def backtrack(start, path):
            if len(path)==len(nums):
                res.append(path[:])
                return

            for i in range(len(nums)):
            	# 因为给定数组不含重复数字, 所以可以直接使用path来充当set
                if nums[i] in path:
                    continue
                path.append(nums[i])
                backtrack(i+1, path)
                path.pop()

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

go版本:

var res [][]int
var visited map[int]bool

func permute(nums []int) [][]int {
	res = [][]int{}
	visited = map[int]bool{}
	backtrack([]int{}, nums)
	return res
}

func backtrack(path, nums []int) {
    if len(path) == len(nums) {
        temp := make([]int, len(path))
        copy(temp, path)
        res = append(res, temp)
	}
    for _, n := range nums {
        if visited[n] {
            continue
        }
        path = append(path, n)
        visited[n] = true
        backtrack(path, nums)
        path = path[:len(path)-1]
        visited[n] = false
    }
}

LeetCode 47. 全排列 II

题目链接:47. 全排列 II

思路:因为给定数组内可能含有重复数字,所以要有一步去重的操作,之前我们也已经做了很多去重的题目, 去重最核心的思路就是排序+比较相邻数字,代码随想录对去重操作还有深一步的扩展,细说了对树层的去重和树枝的去重,详见此篇

Python版本:

class Solution:
    def permuteUnique(self, nums: List[int]) -> List[List[int]]:

        n = len(nums)
        def backtrack(start, path, flag):
            if len(path)==n:
                res.append(path[:])
                return

            for i in range(n):
                # 去重
                if flag[i]:
                    continue
                if i!=0 and nums[i]==nums[i-1] and flag[i-1]==0:
                    continue
                path.append(nums[i])
                flag[i] = 1
                backtrack(i+1, path, flag)
                path.pop()
                flag[i] = 0

        res = []
        flag = [0] * n
        nums.sort()
        backtrack(0, [], flag)
        return res

go版本:

var res [][]int

func permuteUnique(nums []int) [][]int {
	res = [][]int{}
	backTrack(nums,len(nums),[]int{})
	return res
}

func backTrack(nums []int,numsLen int,path []int)  {
	if len(nums)==0{
		p:=make([]int,len(path))
		copy(p,path)
		res = append(res,p)
	}
	used := [21]int{}
	for i:=0;i<numsLen;i++{
		if used[nums[i]+10]==1{
			continue
		}
		cur:=nums[i]
		path = append(path,cur)
		used[nums[i]+10]=1
		nums = append(nums[:i],nums[i+1:]...)
		backTrack(nums,len(nums),path)
		nums = append(nums[:i],append([]int{cur},nums[i:]...)...)
		path = path[:len(path)-1]
	}
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值