1.Univalued Binary Tree
解题思路:递归判断下即可。
type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}
func isUnivalTree(root *TreeNode) bool {
if root == nil {
return true
}
if root.Left != nil && root.Val != root.Left.Val {
return false
}
if root.Right != nil && root.Val != root.Right.Val {
return false
}
ok := true
ok = ok && isUnivalTree(root.Left)
ok = ok && isUnivalTree(root.Right)
return ok
}
2. Numbers With Same Consecutive Differences
解题思路:dfs 枚举即可。
func numsSameConsecDiff(N int, K int) []int {
if N == 1 {
return []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
}
var res []int
var bits [10]int
var dfs func(i int)
dfs = func(idx int) {
if idx == N {
num := 0
for i := 0; i < N; i++ {
num = num*10 + bits[i]
}
res = append(res, num)
return
}
if idx == 0 {
for i := 1; i <= 9; i++ {
bits[idx] = i
dfs(idx + 1)
}
} else {
if bits[idx-1]+K <= 9 {
bits[idx] = bits[idx-1] + K
dfs(idx + 1)
}
// 注意此处 K 为 0 时,只能转移一次,否则会求解出重复元素
if bits[idx-1]-K >= 0 && K > 0 {
bits[idx] = bits[idx-1] - K
dfs(idx + 1)
}
}
return
}
dfs(0)
return res
}
3. Vowel Spellchecker
解题思路:分类处理即可。
func spellchecker(wordlist []string, queries []string) []string {
var ans []string
if len(wordlist) == 0 {
ans = make([]string, len(queries))
return ans
}
sameMap := map[string]string{}
for i := range wordlist {
sameMap[wordlist[i]] = wordlist[i]
}
capMap := map[string][]string{}
for i := range wordlist {
word := strings.ToLower(wordlist[i])
capMap[word] = append(capMap[word], wordlist[i])
}
vowelMap := map[string][]string{}
for i := range wordlist {
word := strings.ToLower(wordlist[i])
var bs []byte
for j := range word {
if word[j] == 'a' || word[j] == 'i' || word[j] == 'o' ||
word[j] == 'e' || word[j] == 'u' {
bs = append(bs, '*')
} else {
bs = append(bs, word[j])
}
}
bss := string(bs)
vowelMap[bss] = append(vowelMap[bss], wordlist[i])
}
for i := range queries {
if _, ok := sameMap[queries[i]]; ok {
ans = append(ans, queries[i])
continue
}
lq := strings.ToLower(queries[i])
if _, ok := capMap[lq]; ok {
ans = append(ans, capMap[lq][0])
continue
}
bs := []byte{}
for j := range lq {
if lq[j] == 'a' || lq[j] == 'e' || lq[j] == 'i' ||
lq[j] == 'o' || lq[j] == 'u' {
bs = append(bs, '*')
} else {
bs = append(bs, lq[j])
}
}
bss := string(bs)
if _, ok := vowelMap[bss]; ok {
ans = append(ans, vowelMap[bss][0])
continue
}
ans = append(ans, "")
}
return ans
}
4. Binary Tree Cameras
解题思路:树形 DP。顺便梳理下一些相关问题求解的动态规划解法。
最小点覆盖集:选择最少点集合关联上树上的所有边。
- 状态定义
dp[i][0]:以 i 为根的子树且顶点 i 不属于点覆盖集中顶点的情况下最少的顶点数
dp[i][1]:以 i 为根的子树且顶点 i 属于点覆盖集中顶点的情况下最少的顶点数
- 状态转移
dp[i][0] = SUM{dp[u][1]},u 为 i 的孩子节点
dp[i][1] = SUM{min{dp[u][0], dp[u][1]}}
最大点独立集:选择最多点集合,其中任意顶点之间不存在边。
- 状态定义
dp[i][0]:以 i 为根的子树且顶点 i 不属于点独立集中顶点的情况下最多的顶点数
dp[i][1]:以 i 为根的子树且顶点 i 属于点独立集中顶点的情况下最多的顶点数
- 状态转移
dp[i][0] = SUM{max{dp[u][0], dp[u][1]}},u 为 i 的孩子节点
dp[i][1] = SUM{dp[u][0]}, u 为 i 的孩子节点
最小点支配集:选择最少的顶点集合使得其余顶点均与该点支配集中的顶点相邻。
- 状态定义
dp[i][0]:以 i 为根的子树且 i 属于支配集且 i 的子树均被覆盖的情况下需要的最少节点数
dp[i][1]:以 i 为根的子树且 i 不属于支配集且 i 的子树均被覆盖且至少一个孩子节点覆盖掉 i 的情况下的最少节点数
dp[i][2]:以 i 为根的子树且 i 不属于支配集且 i 的子树均被覆盖且不存在一个孩子节点覆盖掉 i 的情况下最少的节点数
- 状态转移
dp[i][0] = SUM(min(dp[u][0], dp[u][1], dp[u][2])) + 1,其中 u 为 i 的孩子节点
dp[i][1] 则需要分两种情况讨论,当 i 无孩子节点时,容易 dp[i][1] = inf;当 i 存在孩子节点时,dp[i][1] = SUM(min(dp[u][0], dp[u][1]))且要保证其孩子节点中至少存在一个值是 dp[u][0],因为要保证 i 点被孩子节点覆盖掉嘛
dp[i][2] = SUM(dp[i][1])
,注意一个节点 i 最多能被其父节点覆盖掉,不能被其祖先节点覆盖,因此对于任意一条树上的路径肯定不会存在连续三个节点均不在支配集中`
PS:画棵深度为三层的满多叉树便很容易理解上述的状态转移方程。
const (
inf = 1000010
)
func minInt(a, b int) int {
if a < b {
return a
}
return b
}
func minCameraCover(root *TreeNode) int {
if root == nil {
return 0
}
dp := map[*TreeNode]map[int]int{}
var dfs func(r *TreeNode)
dfs = func(r *TreeNode) {
dp[r] = map[int]int{}
if r.Left == nil && r.Right == nil {
dp[r][0] = 1
dp[r][1] = inf
dp[r][2] = 0
return
}
dp[r][0] = 1
if r.Left != nil {
dfs(r.Left)
dp[r][0] += minInt(minInt(dp[r.Left][0], dp[r.Left][1]), dp[r.Left][2])
dp[r][2] += dp[r.Left][1]
}
if r.Right != nil {
dfs(r.Right)
dp[r][0] += minInt(minInt(dp[r.Right][0], dp[r.Right][1]), dp[r.Right][2])
dp[r][2] += dp[r.Right][1]
}
if r.Left == nil {
dp[r][1] = dp[r.Right][0]
return
}
if r.Right == nil {
dp[r][1] = dp[r.Left][0]
return
}
dp[r][1] = minInt(minInt(dp[r.Left][0]+dp[r.Right][1], dp[r.Left][1]+dp[r.Right][0]), dp[r.Left][0]+dp[r.Right][0])
}
dfs(root)
return minInt(dp[root][0], dp[root][1])
}