75 --82 回溯||深度优先算法

 75  含有 k 个元素的组合

给定两个整数 n 和 k,返回 1 ... n 中所有可能的 k 个数的组合。

力扣https://leetcode-cn.com/problems/uUsW3B/

//要查询n个数字中k个数的组合,先想到深度优先探索
//首先明确跳出条件,k==0的时候说明排列完毕,当数组长小于k的时候可以不必排列
//start 开始的坐标用于避免重复 k 还需要几个数 res 最终结果 original 上次排序的值 arr 数组中的值  
func dfscombine(start,k int,res *[][]int,orignal,arr []int){
	if k==0{
		*res = append(*res,orignal)
		return
	}
	for i:=start;i<len(arr)-k+1;i++{
		tmp:=make([]int,len(orignal))
		copy(tmp,orignal)
		tmp = append(tmp,arr[i])
		dfscombine(i+1,k-1,res,tmp,arr)
	}
}

func combine(n,k int)[][]int{
	var arr []int
	var res [][]int
	for i:=1;i<=n;i++{
		arr = append(arr,i)
	}
	dfscombine(0,k,&res,[]int{},arr)
	return res
}

 76  允许重复选择元素的组合

给定一个无重复元素的正整数数组 candidates 和一个正整数 target ,找出 candidates 中所有可以使数字和为目标数 target 的唯一组合。

candidates 中的数字可以无限制重复被选取。如果至少一个所选数字数量不同,则两种组合是唯一的。 

对于给定的输入,保证和为 target 的唯一组合数少于 150 个。

输入: candidates = [2,3,6,7], target = 7
输出: [[7],[2,2,3]]

力扣https://leetcode-cn.com/problems/Ygoe9J/

//求所有数组值的和为target的和
//跳出条件,当sum==target 此时结果正确,当sum>target跳出,sum<target继续
//candidates 所有的数组,因为允许重复使用某个值 res 用于存储最后结果
//arr 存储之前所有的结果 target 目标值 index 索引代表当前走到了哪一步,防止重复
func innerCombinationSum(candidates []int,res *[][]int,arr []int,target,index int){
	var sum int
	for i:=0;i<len(arr);i++{
		sum = sum + arr[i]
	}
	if sum==target{
		*res = append(*res,arr)
	}else{
		for i:=index;i<len(candidates);i++{
			tmp:=make([]int,len(arr))
			copy(tmp,arr)
			if candidates[i]+sum>target{
				continue
			}
			tmp = append(tmp,candidates[i])
			innerCombinationSum(candidates,res,tmp,target,i)
		}
	}
}

func combinationSum(candidates []int, target int) [][]int {
	var res [][]int
	innerCombinationSum(candidates,&res,[]int{},target,0)
	return res
}

77  含有重复元素集合的组合

给定一个可能有重复数字的整数数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

candidates 中的每个数字在每个组合中只能使用一次,解集不能包含重复的组合。 

力扣https://leetcode-cn.com/problems/4sjJUc/

//与上一题对照来看,区别只在于数组中含有重复,以及数字只使用一次
//使用armap,去掉重复
//使用index = i+1解决数字只能使用一次
//使用sort解决顺序问题
func innerCombinationSumV2(candidates []int,res *[][]int,arr []int,target,index int){
	var sum int
	for i:=0;i<len(arr);i++{
		sum = sum + arr[i]
	}
	if sum==target{
		*res = append(*res,arr)
	}else if sum >target{
		return
	}else{
		armap:=make(map[int]bool)
		for i:=index;i<len(candidates);i++{
			if armap[candidates[i]]{
				continue
			}else {
				armap[candidates[i]] = true
			}
			tmp:=make([]int,len(arr))
			copy(tmp,arr)
			if candidates[i]+sum>target{
				continue
			}
			tmp = append(tmp,candidates[i])
			innerCombinationSumV2(candidates,res,tmp,target,i+1)
		}
	}
}

func combinationSum2(candidates []int, target int) [][]int {
	var res [][]int
	sort.Ints(candidates)
	innerCombinationSumV2(candidates,&res,[]int{},target,0)
	return res
}

78  没有重复元素集合的全排列

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

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

https://leetcode-cn.com/problems/VvJkup/https://leetcode-cn.com/problems/VvJkup/

//全排列第一个想到深度优先探索
//res作为结果 nums表示原先数组的值 arr表示结果
func innerPermute(res *[][]int,nums []int,arr []int){
	if len(nums)==0{
		*res = append(*res,arr)
		return
	}
	for i:=0;i<len(nums);i++{
		tmpnum:=make([]int,len(nums))
		copy(tmpnum,nums)
		tmparr:=make([]int,len(arr))
		copy(tmparr,arr)
		tmparr = append(tmparr,nums[i])
		tmpnum = append(tmpnum[:i], tmpnum[i+1:]...)
		innerPermute(res,tmpnum,tmparr)
	}
}

func permute(nums []int) [][]int {
	var res [][]int
	innerPermute(&res,nums,[]int{})
	return res
}

79  含有重复元素集合的全排列

给定一个可包含重复数字的整数集合 nums ,按任意顺序 返回它所有不重复的全排列。

力扣https://leetcode-cn.com/problems/7p8L0Z/

//与上一题区别只在于一个含有重复一个没有重复,解决重复即可
func innerPermuteUnique(res *[][]int,nums []int,arr []int){
	if len(nums)==0{
		*res = append(*res,arr)
		return
	}
	tmpmap:=make(map[int]bool)
	for i:=0;i<len(nums);i++{
		if tmpmap[nums[i]] == true{
			continue
		}else{
			tmpmap[nums[i]] = true
		}
		tmpnum:=make([]int,len(nums))
		copy(tmpnum,nums)
		tmparr:=make([]int,len(arr))
		copy(tmparr,arr)
		tmparr = append(tmparr,nums[i])
		tmpnum = append(tmpnum[:i], tmpnum[i+1:]...)
		innerPermuteUnique(res,tmpnum,tmparr)
	}
}

func permuteUnique(nums []int) [][]int {
	var res [][]int
	innerPermuteUnique(&res,nums,[]int{})
	return res
}

80  复原ip

https://leetcode-cn.com/problems/0on3uN/https://leetcode-cn.com/problems/0on3uN/

给定一个只包含数字的字符串 s ,用以表示一个 IP 地址,返回所有可能从 s 获得的 有效 IP 地址 。你可以按任何顺序返回答案。

有效 IP 地址 正好由四个整数(每个整数位于 0 到 255 之间组成,且不能含有前导 0),整数之间用 '.' 分隔。

例如:"0.1.2.201" 和 "192.168.1.1" 是 有效 IP 地址,但是 "0.011.255.245"、"192.168.1.312" 和 "192.168@1.1" 是 无效 IP 地址。

func isValidIp(str string)bool{
	if len(str)==0||len(str)>3{
		return false
	}
	num,_:=strconv.Atoi(str)
	if num>255{
		return false
	}
	if str[0]=='0'&&len(str)>1{
		return false
	}
	return true
}

//要求所有可能,第一个想到深度优先遍历
//一定有4个.,当.没有的时候跳出
//0代表.的个数 str 代表已经拼接的 laststr代表上次剩余的
func innerRestoreIpAddresses(o int,str,laststr string,res *[]string ){
	if o==0{
		if isValidIp(laststr){
			*res = append(*res,str+laststr)
		}
		return
	}
	//一个顿号最大3个值
	for i:=0;i<len(laststr)&&i<3;i++{
		if !isValidIp(laststr[:i+1]){
			break
		}
		tmp:=str
		tmp = tmp + laststr[:i+1]
		tmp = tmp + "."
		innerRestoreIpAddresses(o-1,tmp,laststr[i+1:],res)
	}
}

func restoreIpAddresses(s string) []string {
	var res []string
	innerRestoreIpAddresses(3,"",s,&res)
	return res
}

81 生成匹配的括号

https://leetcode-cn.com/problems/IDBivT/https://leetcode-cn.com/problems/IDBivT/正整数 n 代表生成括号的对数,请设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。

func innerGenerateParenthesis(n, open, close int, str string, strs *[]string) {
	if open > n || close > open {
		return
	}
	if len(str) == 2*n {
		*strs = append(*strs, str)
		return
	}
	innerGenerateParenthesis(n, open+1, close, str+"(", strs)
	innerGenerateParenthesis(n, open, close+1, str+")", strs)
}

func generateParenthesis(n int) []string {
	var strs []string
	innerGenerateParenthesis(n, 0, 0, "", &strs)
	return strs
}

82 分割回文子字符串

https://leetcode-cn.com/problems/M99OJA/icon-default.png?t=LA92https://leetcode-cn.com/problems/M99OJA/

给定一个字符串 s ,请将 s 分割成一些子串,使每个子串都是 回文串 ,返回 s 所有可能的分割方案。

回文串 是正着读和反着读都一样的字符串。

func isPalindromeV2(s string)bool{
	start:=0
	end:=len(s)-1
	for start<=end{
		if s[start]!=s[end]{
			return false
		}
		start = start + 1
		end = end - 1
	}
	return true
}


//要求所有的可能方案
//
func innerPartiton(original []string,laststr string ,res *[][]string){
	if len(laststr)==0{
		tmp:=make([]string,len(original))
		copy(tmp,original)
		*res = append(*res,tmp)
		return
	}
	//长度从 1 到 len(laststr)
	for i:=0;i<len(laststr);i++{
		if isPalindromeV2(laststr[:i+1]){
			tmp:=make([]string,len(original))
			copy(tmp,original)
			tmp = append(tmp,laststr[:i+1])
			innerPartiton(tmp,laststr[i+1:],res)
		}else{
			continue
		}
	}
	return
}

func partition(s string) [][]string {
	var res [][]string
	innerPartiton([]string{},s,&res)
	return res
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值