Bootstrap

【代码随想录——回溯算法——二周目】

1. 组合总和

在这里插入图片描述

var (
	path []int
	res  [][]int
)

func combinationSum(candidates []int, target int) [][]int {
	path = make([]int, 0)
	res = make([][]int, 0)
	dfs(candidates,target,0,0)
	return res
}

func dfs(candidates []int, target int,tempTarget int,start int)  {
    if tempTarget>target{
        return
    }
	if tempTarget==target{
		temp := make([]int,len(path))
		copy(temp,path)
		res = append(res, temp)
		return
	}
	for i:=start;i<len(candidates);i++{
		path = append(path, candidates[i])
		dfs(candidates,target,tempTarget+candidates[i],i)
		path = path[:len(path)-1]
	}
}

2. 组合总和2

在这里插入图片描述
需要先对候选人进行一个排序

2.1 使用used数组

var (
    res [][]int
    path  []int
    used  []bool
)
func combinationSum2(candidates []int, target int) [][]int {
    res, path = make([][]int, 0), make([]int, 0, len(candidates))
    used = make([]bool, len(candidates))
    sort.Ints(candidates)   // 排序,为剪枝做准备
    dfs(candidates, 0, target)
    return res
}

func dfs(candidates []int, start int, target int) {
    if target == 0 {   // target 不断减小,如果为0说明达到了目标值
        tmp := make([]int, len(path))
        copy(tmp, path)
        res = append(res, tmp)
        return
    }
    for i := start; i < len(candidates); i++ {
        if candidates[i] > target {  // 剪枝,提前返回
            break
        }
        // 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
        }
        path = append(path, candidates[i])
        used[i] = true
        dfs(candidates, i+1, target - candidates[i])
        used[i] = false
        path = path[:len(path) - 1]
    }
}

2.2 不使用used数组

var (
    res [][]int
    path  []int
)
func combinationSum2(candidates []int, target int) [][]int {
    res, path = make([][]int, 0), make([]int, 0, len(candidates))
    sort.Ints(candidates)   // 排序,为剪枝做准备
    dfs(candidates, 0, target)
    return res
}

func dfs(candidates []int, start int, target int) {
    if target == 0 {   // target 不断减小,如果为0说明达到了目标值
        tmp := make([]int, len(path))
        copy(tmp, path)
        res = append(res, tmp)
        return
    }
    for i := start; i < len(candidates); i++ {
        if candidates[i] > target {  // 剪枝,提前返回
            break
        }
        // i != start 限制了这不对深度遍历到达的此值去重
        if i != start && candidates[i] == candidates[i-1] { // 去重
            continue
        }
        path = append(path, candidates[i])
        dfs(candidates, i+1, target - candidates[i])
        path = path[:len(path) - 1]
    }
}

3. 分割回文串

在这里插入图片描述

var (
	path []string
	res  [][]string
)

func partition(s string) [][]string {
	path = make([]string, 0)
	res = make([][]string, 0)
	dfs(s,0)
	return res
}

func dfs(s string, start int) {
	if len(s) == start { //表明找到了一个切割方案
		temp := make([]string, len(path))
		copy(temp, path)
		res = append(res, temp)
	}
	for i := start; i < len(s); i++ {
		if isPalindrome(s[start:i+1]){
			//表名当前是一个回文串
			path = append(path, s[start:i+1])
			dfs(s,i+1)
			path = path[:len(path)-1]
		}
	}
}

func isPalindrome(s string) bool {
	for i:=0;i<len(s)/2;i++{
		if s[i]!=s[len(s)-i-1]{
			return false
		}
	}
	return true
}

4. 复原IP地址

在这里插入图片描述

var (
	path []string
	res  []string
)

func restoreIpAddresses(s string) []string {
	path = make([]string, 0)
	res = make([]string, 0)
	dfs(s, 0, 4)
	return res
}

func dfs(s string, start int, remain int) {
	if remain == 0 && start == len(s) { //表明找到了一个切割方案
		temp := path[0]
		for i := 1; i < len(path); i++ {
			temp = temp + "." + path[i]
		}
		res = append(res, temp)
	}
	for i := start; i < start+3 && i < len(s); i++ {
		if isValidNumber(s[start : i+1]) {
			//表名当前是一个回文串
			path = append(path, s[start:i+1])
			dfs(s, i+1, remain-1)
			path = path[:len(path)-1]
		}
	}
}

func isValidNumber(s string) bool {
	//前导零判断
	if len(s) > 1 && s[0] == '0' {
		return false
	}
	//判断数字大小是否在小于255
	num, _ := strconv.Atoi(s)
	if num > 255 {
		return false
	}
	return true
}

5. 子集问题

在这里插入图片描述

var (
    path   []int
    res  [][]int
)
func subsets(nums []int) [][]int {
    res, path = make([][]int, 0), make([]int, 0, len(nums))
    dfs(nums, 0)
    return res
}
func dfs(nums []int, start int) {
    tmp := make([]int, len(path))
    copy(tmp, path)
    res = append(res, tmp)

    for i := start; i < len(nums); i++ {
        path = append(path, nums[i])
        dfs(nums, i+1)
        path = path[:len(path)-1]
    }
}
;