首页 > 其他分享 >代码随想录day23 || 39 组合总和,40 组合总和2,131 分割回文串

代码随想录day23 || 39 组合总和,40 组合总和2,131 分割回文串

时间:2024-08-08 13:30:05浏览次数:8  
标签:return 组合 int res 随想录 li path append 总和

39 组合总和

func combinationSum(candidates []int, target int) [][]int {
	// 思路,组合问题考虑回溯算法,考虑到元素可能重复问题,所以,树的最大深度应该是target / min(candudates) + 1
	var path = []int{}
	var res = [][]int{}
	backtracking(target, candidates, &path, &res)
	return res
}

func backtracking(target int, li []int, path *[]int, res *[][]int){
	// 递归/回溯终止条件,收集结果
	if sum(*path) == target {
		var copypath = make([]int, len(*path))
		copy(copypath, *path)
		*res = append(*res, copypath)
		return
	}

	// 剪枝,如果路径和大于target,不再递归回溯
	if sum(*path) > target {
		return
	}

	// 递归回溯
	for i:=0; i<len(li); i++ {
		*path = append(*path, li[i])
		backtracking(target, li[i : ], path, res)
		*path = (*path)[0 : len(*path) - 1]
	}
	return
}

func sum(li []int) int {
	var sum int
	for _, l := range li {
		sum += l
	}
	return sum
}

40 组合之和2

go语言允许切片的区间取值li[start : end], start == end == len(li) 这种语法是正确的,但是li[len(li)] 这种索引取值会报错out of range

func combinationSum2(candidates []int, target int) [][]int {
	// 思路,组合问题考虑回溯算法
	var path = []int{}
	var res = [][]int{}
	candidates = quicksort(candidates)
	backtracking(target, candidates, &path, &res)
	return res
}

func backtracking(target int, li []int, path *[]int, res *[][]int){
	if sum(*path) == target {
		var copypath = make([]int, len(*path))
		copy(copypath, *path)
		*res = append(*res, copypath)
		return
	}

	// 剪枝,如果路径和大于target,不再递归回溯
	if sum(*path) > target {
		return
	}

	for i:=0; i<len(li); i++ {
		// 处理重复元素情况
		if i > 0 && li[i - 1] == li[i] {
			// 元素重复,那么第二个元素结果集必然包含在第一个元素结果集中
			continue
		}
		*path = append(*path, li[i])
		backtracking(target, li[i+1 : ], path, res) // 不能重复,那就传入数组的时候不包含首元素就行了 !!! tmd li[start: end]  start == end == len(li), 这样语法居然不会报错,活久见
		*path = (*path)[0 : len(*path) - 1]
	}
	return
}

func sum(li []int) int {
	var sum int
	for _, l := range li {
		sum += l
	}
	return sum
}

func quicksort(li []int) []int {
	// 取首位作为中值,划分大于中值区间和小于中值区间,然后递归
	if len(li) == 0{
		return nil
	}
	pivot := li[0]
	var left, right, mid []int
	for _, l := range li {
		if l > pivot {
			right = append(right, l)
		}else if l < pivot{
			left = append(left, l)
		}else {
			mid = append(mid, l)
		}
	}

	left = quicksort(left)
	right = quicksort(right)

	return append(left, append(mid, right...)...)
}

131 分割回文串

func partition(s string) [][]string {
	// 基础的回溯收集思路,外加一个判断回文串的函数
	var path = []string{}
	var res = [][]string{}
	backtracking(s, 0, &path, &res)
	return res
}

func backtracking(s string, div int, path *[]string, res *[][]string) { // div 切割位置
	if div == len(s) { // 遇到叶子节点,说明此时path元素已经全是回文,收集到结果集中
		var copypath = make([]string, len(*path))
		copy(copypath, *path)
		*res = append(*res, copypath)
		return
	}

	for i:=div; i<len(s); i++{
		if recoverStr(s[div: i+1]){
			*path = append(*path, s[div: i+1])
			backtracking(s, i+1, path, res)
			*path = (*path)[0 : len(*path) - 1]
		}else {
			continue // 剪枝本层的该节点以及对应子树
		}
	}
	return
}

func recoverStr(s string) bool {
	if len(s) == 0{
		return false
	}

	if len(s) == 1{
		return true
	}
	left := 0
	right := len(s) - 1

	for left < right {
		if s[left] == s[right] {
			left++
			right--
		}else {
			return false
		}
	}
	return true
}

// 此题理解不深刻

指针path *[]int 添加到指针 res *[][]int 产生的思考

func backtracking(s string, path *[]byte, res *[]string) {
	if recover(*path) {
		*res = append(*res, string(*path)) // string(*path) 相当于隐式创建了一个string变量,用来存储
		return
	}
	...
}


func backtracking2(s string, path *[]int, res *[][]int) {
	if recover(*path) {
		*res = append(*res, *path)
		return
	}
	...
}

func backtracking3(s string, path *[]int, res *[][]int) {
	if recover(*path) {
		var copypath []int
		copy(copypath, *path)
		*res = append(*res, copypath)
		return
	}
	...
}


// 上面三种写法保存结果集,其中1,3是正确的,2是错误的,对于收集的同样长度的结果集,所有结果都是重复的,并且等于最后收集的结果
// 切片在go中是有三个数据的结果,1,指向底层数组的指针 2,切片长度 3,切片容量
// 对于指针类型的引用,path代表的是指向底层数组的指针,*path代表的是底层数组,所以,res append操作,每一个元素指向的也是*path的底层数组
// 如果对于同一个长度的数组,我们在回溯[1,2,3] 回溯[3] 添加[4], 由于没有改变底层数组的长度,所以,go没有开辟新的存储空间并指向新的底层数组,所以我们的修改都是基于原有的底层数组之上,这样导致我们这边的修改,会对res中以及保存的指向相同底层数组的结果集发生修改。所以我们需要对*path进行赋值到其他变量,用来指向不同的空间,以用来避免底层修改产生的连锁反应

// 另一个方面,可以预见到的是,如果*path = []int{1}, res append,  *path=append(..., 2), res append, 这种情况,res不会被修改,因为,path切片扩容了会开辟新的内存空间,并把原来的切片值放入新空间,但是res指向的还是原来的底层数组,不会发生改变

标签:return,组合,int,res,随想录,li,path,append,总和
From: https://www.cnblogs.com/zhougongjin55/p/18348732

相关文章

  • 代码随想录算法训练营第63天 | SPFA算法优化+变式
    94.城市间货物运输Ihttps://kamacoder.com/problempage.php?pid=1152Bellman_ford队列优化算法(又名SPFA)https://www.programmercarl.com/kamacoder/0094.城市间货物运输I-SPFA.html95.城市间货物运输IIhttps://kamacoder.com/problempage.php?pid=1153bellman_ford之判......
  • permutation 不仅仅排列,组合也可以
    排序:1——n所有不重复的排列include<bits/stdc++.h>usingnamespacestd;inta[10];intmain(){intn,i,j=1,k;cin>>n;for(i=1;i<=n;i++){a[i]=i;//a[1~n]=1——n}do{for(k=1;k<=n;k++)printf("%5d",a[k]);printf("\n");}whi......
  • 「代码随想录算法训练营」第三十二天 | 动态规划 part5
    52.携带研究材料题目链接:https://kamacoder.com/problempage.php?pid=1052文章讲解:https://programmercarl.com/背包问题理论基础完全背包.html视频讲解:https://www.bilibili.com/video/BV1uK411o7c9/题目状态:看题解过思路:在0-1背包问题中,每个物品只能选择一次,即每个物品......
  • 如何修复当我将组合放入这样的列表 ([ 地址 )] 时,它说它是空的并且不打印任何内容的错
    我使用python生成74个字符串的组合,并使用两个组合字符串,即“0123456789abcdef”和“QQQQQQ33”。我希望QQQQQ33位于括号[]中,以便在使用它时,它使用完整的字符串,而不是生成字符串与0123456789abcdef的所有组合。每当我使用括号时,这就像是唯一的方法它完整​​地打印......
  • Studying-代码随想录训练营day62| Floyd 算法精讲、A*算法精讲(A star算法)、最短路算法
    第62天,完结撒花*★,°*:.☆( ̄▽ ̄)/$:*.°★*,最后的两个算法学习,编程语言C++目录Floyd算法精讲A*算法精讲(Astar算法) A*算法 复杂度分析 A*算法的缺点最短路算法总结篇 图论总结深搜和广搜并查集最小生成树 拓扑排序 最短路算法 总结 Floyd算法精讲......
  • 代码随想录day 48 每日温度 | 下一个更大元素 I | 下一个更大元素II
    每日温度每日温度解题思路单调栈的意思其实是指栈内的元素单调递增/递减,我们可以通过这个特性存储元素的下标,然后每次入栈时与栈顶坐标的元素进行比较,如果小于等于就不需要弹出直接存入,如果大于,则需要不断弹出栈顶直到遇到一个小于其的栈顶元素或者栈为空。知识点单调栈心......
  • 【ES6】使用Set和Map进行全组合判断
    判断数据集是否为全组合关系例如下列表格,字段1包含(甲、乙)值,字段2包含(a、b)值,字段3包含(1、2、3)值,每种组合情况都可以在数据集的行记录中找到有且仅有的一条。字段1字段2字段3甲a1甲a2甲a3甲b1甲b2甲b3乙a1乙a2乙a3乙b1乙b2乙b3要求函数输入以下格式数据,输出布尔值。const......
  • 代码随想录算法训练营day06|242.有效的字母异位词,349.两个数组的交集,202.快乐数,1.两数
    242.有效的字母异位词题目链接:https://leetcode.cn/problems/valid-anagram/description/我的代码:classSolution{public:boolisAnagram(strings,stringt){if(s.size()==t.size()){intrecord[26]={0};for(inti=0;i......
  • 代码随想录Day8
    344.反转字符串编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组s的形式给出。不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用\(O(1)\)的额外空间解决这一问题。示例1:输入:s=["h","e","l","l","o"]输出:["o","l","l","e",&q......
  • 「代码随想录算法训练营」第三十一天 | 动态规划 part4
    1049.最后一块石头的重量II题目链接:https://leetcode.cn/problems/last-stone-weight-ii/题目难度:中等文章讲解:https://programmercarl.com/1049.最后一块石头的重量II.html视频讲解:https://www.bilibili.com/video/BV14M411C7oV/题目状态:看题解过思路:本题本质上就是将......