注意:使用切片表达式的得到的切片和原来的切片共用同一个底层数组
剪枝操作:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uvNUUAKq-1640443748589)(https://gitee.com/CJ-cooper6/picgo/raw/master/image-20211130172501586(1)].png)
代码
var res [][]int
var ans []int
func combine(n int, k int) [][]int {
res=[][]int{}
ans=[]int{}
backtrack(n,k,1)
return res
}
func backtrack(n,k,index int){
if len(ans)==k{
a:=make([]int,len(ans)) //这里要创建新的切片,不然后面对修改ans会改变res的,因为共用一个底层数组
copy(a,ans)
res=append(res,a)
return
}
for i:=index;i<=n-(k-len(ans))+1;i++{//剪枝操作,如果没有足够的元素不进行下一步
ans=append(ans,i)
backtrack(n,k,i+1)
ans=ans[0:len(ans)-1]
}
}
var result [][]int
var ans []int
var sum int
func combinationSum3(k int, n int) [][]int {
result=[][]int{}
ans=[]int{}
sum=0
backstrack(k,n,sum,1)
return result
}
func backstrack(k,n,sum,index int){
if sum > n{
return
}
if len(ans)==k{
if sum == n{
t:=make([]int,k)
copy(t,ans)
result=append(result,t)
return
}
}
for i:=index;i<=9-(k-len(ans))+1;i++{
ans=append(ans,i)
sum+=i
backstrack(k,n,sum,i+1)
sum-=i
ans=ans[:len(ans)-1]
}
}
本题和之前题不同,这道题是多个集合求组合,而之前的是一个集合求组合
var m map[byte][]byte
var res []string
var ans []byte
func letterCombinations(digits string) []string {
if len(digits)>4 || len(digits)==0{
return []string{}
}
m=map[byte][]byte{
'0':{},
'1':{},
'2':{'a','b','c'},
'3':{'d','e','f'},
'4':{'g','h','i'},
'5':{'j','k','l'},
'6':{'m','n','o'},
'7':{'p','q','r','s'},
'8':{'t','u','v'},
'9':{'w','x','y','z'},
}
res=[]string{}
ans=[]byte{}
str:=[]byte(digits)
backtrack(len(str),str,0)
return res
}
func backtrack(n int,arr []byte,outindex int){
if len(ans)==n{
t:=string(ans)
res=append(res,t)
return
}
letter:=m[arr[outindex]] // 取数字对应的字符集
for i:=0;i<len(letter);i++{
ans=append(ans,letter[i])
backtrack(n,arr,outindex+1)
ans=ans[:len(ans)-1] //回溯
}
}
var res [][]int
var ans []int
func combinationSum(candidates []int, target int) [][]int {
res=[][]int{}
ans=[]int{}
sort.Ints(candidates)
backstrack(candidates,target,0,0)
return res
}
func backstrack(candidates []int,target int,sum int,index int){
if sum > target{
return
}
if sum == target{
t:=make([]int,len(ans))
copy(t,ans)
res=append(res,t)
return
}
for i:=index;i<len(candidates);i++{
sum+=candidates[i]
ans=append(ans,candidates[i])
backstrack(candidates,target,sum,i)
sum-=ans[len(ans)-1]
ans=ans[:len(ans)-1]
}
}
这道题关键是元素在同一个组合内是可以重复的,怎么重复都没事,但两个组合不能相同。
ued
代码
var res [][]int
var ans []int
var used []bool
func combinationSum2(candidates []int, target int) [][]int {
res = [][]int{}
ans = []int{}
used = make([]bool,len(candidates))
sort.Ints(candidates)
backstrack(candidates,target,0,0,used)
return res
}
func backstrack(candidates []int,target int,sum int,index int,used []bool){
if sum == target{
t:=make([]int,len(ans))
copy(t,ans)
res=append(res,t)
return
}
for i:=index;i<len(candidates) && sum+candidates[i] <= target;i++{
// used[i - 1] == true,说明同一树支candidates[i - 1]使用过
// used[i - 1] == false,说明同一树层candidates[i - 1]使用过
// 要对同一树层使用过的元素进行跳过
if i>0 && candidates[i]==candidates[i-1] && used[i-1]==false{
continue
}
sum+=candidates[i]
ans=append(ans,candidates[i])
used[i]=true
backstrack(candidates,target,sum,i+1,used)
used[i]=false
sum-=ans[len(ans)-1]
ans=ans[:len(ans)-1]
}
}
var res [][]int
var ans []int
func subsets(nums []int) [][]int {
res=[][]int{}
ans=[]int{}
backstrack(nums,0)
return res
}
func backstrack(nums []int,index int){
t:=make([]int,len(ans))
copy(t,ans)
res=append(res,t)
for i:=index;i<len(nums);i++{
ans=append(ans,nums[i])
backstrack(nums,i+1)
ans=ans[:len(ans)-1]
}
}
var res [][]int
var ans []int
func permute(nums []int) [][]int {
res = [][]int{}
ans = []int{}
used := make([]bool,len(nums))
backstrack(nums,used)
return res
}
func backstrack(nums []int,used []bool){
if len(ans) == len(nums){
t:=make([]int,len(ans))
copy(t,ans)
res=append(res,t)
return
}
for i:=0;i<len(nums);i++{
if used[i]==false{
ans=append(ans,nums[i])
used[i]=true
}else{
continue
}
backstrack(nums,used)
used[i]=false
ans=ans[:len(ans)-1]
}
}
var res [][]int
var ans []int
func permuteUnique(nums []int) [][]int {
res = [][]int{}
ans = []int{}
used := make([]bool,len(nums))
sort.Ints(nums)
backstrack(nums,used)
return res
}
func backstrack(nums []int,used []bool){
if len(ans) == len(nums){
t:=make([]int,len(ans))
copy(t,ans)
res=append(res,t)
return
}
for i:=0;i<len(nums);i++{
if i>0 && nums[i]==nums[i-1] && used[i-1]==false{
continue
}
if used[i]==false{
ans=append(ans,nums[i])
used[i]=true
}else{
continue
}
backstrack(nums,used)
used[i]=false
ans=ans[:len(ans)-1]
}
}
if i>0 && nums[i]==nums[i-1] && used[i-1]==false{
continue
}
if used[i]==false{
ans=append(ans,nums[i])
used[i]=true
}else{
continue
}
backstrack(nums,used)
used[i]=false
ans=ans[:len(ans)-1]
}
}