101.分割等和子集
思路:面对一堆数字喝一个目标值的时候,有以下几种情况,数字中是否包含重复数字,数字中的数是否可以被重复选择。这种需要进行分类讨论。
这个题目是属于:不能重复选择的类型,那就按照0-1背包的写法,写成二维数组dp[i][j]表示前0-i的下标能否组成目标值j,nums放在外层,如果写一维的话,需要注意在两层写法的时候不一样。
func canPartition(nums []int) bool {
n := len(nums)
if n < 2 {
return false
}
sum, max := 0, 0
for _, v := range nums {
sum += v
if v > max {
max = v
}
}
if sum%2 != 0 {
return false
}
target := sum / 2
if max > target {
return false
}
dp := make([][]bool, n)
for i := range dp {
dp[i] = make([]bool, target+1)
}
for i := 0; i < n; i++ {
dp[i][0] = true
}
dp[0][nums[0]] = true
for i := 1; i < n; i++ {
v := nums[i]
for j := 1; j <= target; j++ {
if j >= v {
dp[i][j] = dp[i-1][j] || dp[i-1][j-v]
} else {
dp[i][j] = dp[i-1][j]
}
}
}
// fmt.Println(dp)
return dp[n-1][target]
}
102.加减的目标值
思路:dfs
103.最少的硬币数目
思路:这是典型的课重复选择的问题,硬币数可以重复选择,可重复选的可以用一维。
104.排列的数目
思路:这里典型的是可以重复选的类型,nums放在里面。
func combinationSum4(nums []int, target int) int {
dp := make([]int, target+1)
dp[0] = 1
for i := 1; i <= target; i++ {
for j := 0; j < len(nums); j++ {
if i >= nums[j] {
dp[i] += dp[i-nums[j]]
}
}
}
return dp[target]
}
105.岛屿的最大面积
dfs,在涉及岛屿的时候,在遍历结束后可以淹没岛屿表示已经遍历了。
106.二分图
dfs或者bfs
107.矩阵中的距离
bfs
108.单词演变
双向bfs,双向bfs的核心每次都会选择集合小的那头进行遍历,能很大的减少遍历数。
109.开密码锁
bfs
110.所有路径
dfs