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]
}
}