第3周 树、递归、分治、回溯

2021-12-02
21分钟阅读时长

题目数量:29+

第6课 | 树、二叉树、二叉搜索树

1. 树、二叉树、二叉搜索树的实现和特性

参考链接

思考题

树的面试题解法一般都是递归,为什么? 说明:同学们可以将自己的思考写在课程下方的留言区一起讨论,也可以写在第 2 周的学习总结中。

2. 实战题目解析:二叉树的中序遍历

参考链接

实战题目 / 课后作业

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
// 递归
func inorderTraversal1(root *TreeNode) []int {
    var inorder func (root *TreeNode)
    var res []int
    inorder = func (root *TreeNode) {
        if root == nil {
            return
        }
        inorder(root.Left)
        res = append(res, root.Val)
        inorder(root.Right)
    }
    inorder(root)
    return res
}

// 直接迭代
func inorderTraversal2(root *TreeNode) (res []int) {
    stack := []*TreeNode{}
    for root != nil || len(stack) > 0 {
        for root != nil {
            stack = append(stack, root)
            root = root.Left
        }
        root = stack[len(stack)-1]
        stack = stack[:len(stack) - 1]
        res = append(res, root.Val)
        root = root.Right
    }
    return res
}

type Node struct {
    N *TreeNode
    Color int
}
// 着色迭代遍历
func inorderTraversal(root *TreeNode) (res []int) {
    if root == nil {
        return
    }
    stack := []*Node{&Node{N:root, Color:0}}
    for len(stack) > 0 {
        node := stack[len(stack) - 1]
        stack = stack[:len(stack) - 1]
        if node.Color == 1 {
            res = append(res, node.N.Val)
        } else {
            if node.N.Right != nil {
                stack = append(stack, &Node{N:node.N.Right, Color: 0})
            }
            node.Color = 1
            stack = append(stack, node)
            if node.N.Left != nil {
                stack = append(stack, &Node{N:node.N.Left, Color: 0})
            }
        }
    }
    return res
}

// Morris 中序遍历
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
// 递归
func preorderTraversal1(root *TreeNode) (res []int) {
    var preorder func (root *TreeNode)
    preorder = func (root *TreeNode) {
        if root == nil {
            return
        }
        res = append(res, root.Val)
        preorder(root.Left)
        preorder(root.Right)
    }
    preorder(root)
    return
}

// 迭代
func preorderTraversal2(root *TreeNode) (res []int) {
    if root == nil {
        return
    }
    stack := []*TreeNode{root}
    for len(stack) > 0 {
        root = stack[len(stack) - 1]
        stack = stack[:len(stack) - 1]
        res = append(res, root.Val)
        if root.Right != nil {
            stack = append(stack, root.Right)
        }
        if root.Left != nil {
            stack = append(stack, root.Left)
        }
    }
    return
}

type Node struct {
    N *TreeNode
    Color int
}
// 着色迭代遍历
func preorderTraversal(root *TreeNode) (res []int) {
    if root == nil {
        return
    }
    stack := []*Node{&Node{N:root, Color:0}}
    for len(stack) > 0 {
        node := stack[len(stack) - 1]
        stack = stack[:len(stack) - 1]
        if node.Color == 1 {
            res = append(res, node.N.Val)
        } else {
            if node.N.Right != nil {
                stack = append(stack, &Node{N:node.N.Right, Color: 0})
            }
            if node.N.Left != nil {
                stack = append(stack, &Node{N:node.N.Left, Color: 0})
            }
            node.Color = 1
            stack = append(stack, node)
        }
    }
    return res
}

// Morris 遍历
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func postorderTraversal1(root *TreeNode) (res []int) {
    var postorder func(root *TreeNode)
    postorder = func(root *TreeNode) {
        if root == nil {
            return
        }
        postorder(root.Left)
        postorder(root.Right)
        res = append(res, root.Val)
    }
    postorder(root)
    return
}

type Node struct {
    N *TreeNode
    Color int
}
// 着色迭代遍历
func postorderTraversal2(root *TreeNode) (res []int) {
    if root == nil {
        return
    }
    stack := []*Node{&Node{N:root, Color:0}}
    for len(stack) > 0 {
        node := stack[len(stack) - 1]
        stack = stack[:len(stack) - 1]
        if node.Color == 1 {
            res = append(res, node.N.Val)
        } else {
            node.Color = 1
            stack = append(stack, node)
            if node.N.Right != nil {
                stack = append(stack, &Node{N:node.N.Right, Color: 0})
            }
            if node.N.Left != nil {
                stack = append(stack, &Node{N:node.N.Left, Color: 0})
            }
        }
    }
    return res
}

// 迭代 需要仔细体会
func postorderTraversal(root *TreeNode) (res []int) {
    stack := []*TreeNode{}
    var prev *TreeNode
    for root != nil || len(stack) > 0 {
        for root != nil {
            stack = append(stack, root)
            root = root.Left
        }
        root = stack[len(stack)-1]
        stack = stack[:len(stack)-1]
        if root.Right == nil || root.Right == prev {
            res = append(res, root.Val)
            prev = root
            root = nil
        } else {
            stack = append(stack, root)
            root = root.Right
        }
    }
    return res
}

// Morris 遍历
/**
 * Definition for a Node.
 * type Node struct {
 *     Val int
 *     Children []*Node
 * }
 */

func postorder1(root *Node) (res []int) {
    var order func(root *Node)
    order = func(root *Node) {
        if root == nil {
            return
        }
        for _, children := range root.Children {
            order(children)
        }
        res = append(res, root.Val)
    }
    order(root)
    return
}

// 性能更好
func postorder2(root *Node) (res []int) {
    var order func(root *Node)
    order = func(root *Node) {
        if root == nil {
            return
        }
        n := len(root.Children)
        for i := 0; i < n; i++ {
            order(root.Children[i])
        }
        res = append(res, root.Val)
    }
    order(root)
    return
}

// 迭代
func postorder(root *Node) (res []int) {
    if root == nil {
        return
    }
    stack := []*Node{root}
    for len(stack) > 0 {
        root = stack[len(stack)-1]
        stack = stack[:len(stack)-1]
        res = append(res, root.Val)
        for n, i := len(root.Children), 0; i < n; i++ {
            stack = append(stack, root.Children[i])
        }
    }
    return reverse(res)
}
func reverse(s []int) []int {
    for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
        s[i], s[j] = s[j], s[i]
    }
    return s
}
/**
 * Definition for a Node.
 * type Node struct {
 *     Val int
 *     Children []*Node
 * }
 */

func preorder1(root *Node) (res []int) {
    var pre func(root *Node)
    pre = func(root *Node) {
        if root == nil {
            return
        }
        res = append(res, root.Val)
        for _, children := range root.Children {
            pre(children)
        }
    }
    pre(root)
    return
}

// 性能更好
func preorder2(root *Node) (res []int) {
    var pre func(root *Node)
    pre = func(root *Node) {
        if root == nil {
            return
        }
        res = append(res, root.Val)
        n := len(root.Children)
        for i := 0; i < n; i++ {
            pre(root.Children[i])
        }
    }
    pre(root)
    return
}

// 迭代
func preorder(root *Node) (res []int) {
    if root == nil {
        return
    }
    stack := []*Node{root}
    for len(stack) > 0 {
        root = stack[len(stack)-1]
        stack = stack[:len(stack)-1]
        res = append(res, root.Val)
        for idx := len(root.Children) - 1; idx >= 0; idx-- {
            stack = append(stack, root.Children[idx])
        }
    }
    return
}
/**
 * Definition for a Node.
 * type Node struct {
 *     Val int
 *     Children []*Node
 * }
 */
// bfs
func levelOrder(root *Node) (res [][]int) {
    if root == nil {
        return
    }
    queue := []*Node{root}
    for len(queue) > 0 {
        n := len(queue)
        tmp := []*Node{}
        level := []int{}
        for i := 0; i < n; i++ {
            level = append(level, queue[i].Val)
            for _, c := range queue[i].Children {
                tmp = append(tmp, c)
            }
        }
        res = append(res, level)
        queue = tmp
    }
    return res
}

第6课 | 堆和二叉堆、图

1. 堆和二叉堆的实现和特性

参考链接

2. 实战题目解析:最小的k个数、滑动窗口最大值等问题

实战例题

// 快排思想
// 参考:https://leetcode-cn.com/problems/zui-xiao-de-kge-shu-lcof/solution/3chong-jie-fa-miao-sha-topkkuai-pai-dui-er-cha-sou/
func getLeastNumbers(arr []int, k int) []int {
    if k == 0 || len(arr) == 0 {
        return nil
    }
    return quickSort(arr, 0, len(arr) - 1, k - 1)
    //return arr[:k]
}

func quickSort(arr []int, l, r, k int) []int {
    idx := partition(arr, l, r)
    if idx == k {
        return arr[:k+1]
    }
    if idx < k {
        return quickSort(arr, idx + 1, r, k)
    } else { // idx > k
        return quickSort(arr, l, idx - 1, k)
    }
}

func partition(arr []int, l, r int) int {
    mid := arr[l]
    i, j := l + 1, r
    for {
        for i <= j && arr[i] <= mid {
            i++
        }
        for i <= j && arr[j] >= mid {
            j--
        }
        if i >= j {
            break
        }
        arr[i], arr[j] = arr[j], arr[i]
    }
    arr[l], arr[j] = arr[j], mid
    return j
}
// 双端队列
func maxSlidingWindow(nums []int, k int) (res []int) {
    dq := []int{}
    for i := 0; i < len(nums); i++ {
        // 移除越界
        if len(dq) > 0 && dq[0] <= i - k {
            dq = dq[1:]
        }
        // 移除比当前数小的
        for len(dq) > 0 && nums[dq[len(dq)-1]] < nums[i] {
            dq = dq[:len(dq)-1]
        }
        dq = append(dq, i)
        if i >= k - 1 {
            res = append(res, nums[dq[0]])
        }
    }
    return res
}
// 大顶堆
type IHeap [][2]int

func (h IHeap) Len() int           { return len(h) }
func (h IHeap) Less(i, j int) bool { return h[i][1] < h[j][1] }
func (h IHeap) Swap(i, j int)      { h[i], h[j] = h[j], h[i] }

func (h *IHeap) Push(x interface{}) {
    *h = append(*h, x.([2]int))
}

func (h *IHeap) Pop() interface{} {
    old := *h
    n := len(old)
    x := old[n-1]
    *h = old[0 : n-1]
    return x
}

func topKFrequent(nums []int, k int) []int {
    
}

课后作业

// 方法一:动态规划 最优
func nthUglyNumber(n int) int {
    dp := make([]int, n + 1)
    dp[1] = 1
    p2, p3, p5 := 1, 1, 1
    for i := 2; i <= n; i++ {
        x2, x3, x5 := dp[p2]*2, dp[p3]*3, dp[p5]*5
        dp[i] = min(min(x2, x3), x5)
        if dp[i] == x2 {
            p2++
        }
        if dp[i] == x3 {
            p3++
        }
        if dp[i] == x5 {
            p5++
        }
    }
    return dp[n]
}
func min(a, b int) int {
    if a < b {
        return a
    }
    return b
}
// 方法二:小顶堆
var factors = []int{2, 3, 5}
func nthUglyNumber(n int) int {
    h := &hp{sort.IntSlice{1}}
    seem := map[int]struct{}{1:{}}
    for i := 2; i <= n; i++ {
        v := heap.Pop(h).(int)
        if i == n {
            return v
        }
        for _, p := range factors {
            pv := p * v
            if _, ok := seem[pv]; !ok {
                heap.Push(h, pv)
                seem[pv] = struct{}{}
            }
        }
    }
}

type hp struct{sort.IntSlice }

func (h *hp) Push(v interface{}) {
    h.IntSlice = append(h.IntSlice, v.(int))
}

func (h *hp) Pop() interface{} {
    a := h.IntSlice
    v := a[len(a) - 1]
    h.IntSlice = a[:len(a) - 1]
    return v
}
type IHeap [][2]int
func (h IHeap) Len() int { return len(h) }
func (h IHeap) Less(i, j int) bool { return h[i][1] < h[j][1] }
func (h IHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }

func (h *IHeap) Push(v interface{}) {
    *h = append(*h, v.([2]int))
}

func (h *IHeap) Pop() interface{} {
    old := *h
    v := old[len(old) - 1]
    *h = old[:len(old) - 1]
    return v
}

func topKFrequent(nums []int, k int) []int {
    mp := map[int]int{}
    for _, num := range nums {
        mp[num]++
    }
    h := &IHeap{}
    heap.Init(h)
    for key, value := range mp {
        heap.Push(h, [2]int{key, value})
        if h.Len() > k {
            heap.Pop(h)
        }
    }
    res := make([]int, k)
    for i := 0; i < k; i++ {
        res[k - i - 1] = heap.Pop(h).([2]int)[0]
    }
    return res
}

3. 图的实现和特性

思考题

  • 自己画一下有向有权图

参考链接

var fx = [][2]int{{0, 1}, {1, 0}, {-1, 0}, {0, -1}}
// dfs
func numIslands(grid [][]byte) (res int) {
    n, m := len(grid), len(grid[0])
    var dfs func (x, y int)
    dfs = func (x, y int) {
        grid[x][y] = 'x'
        for _, d := range fx {
            nx, ny := x + d[0], y + d[1]
            if 0 <= nx && nx < n && 0 <= ny && ny < m && grid[nx][ny] ==  '1' {
                dfs(nx, ny)
            }
        }
    }
    for i := 0; i < n; i++ {
        for j := 0; j < m; j++ {
            if grid[i][j] == '1' {
                res++
                dfs(i, j)
            }
        }
    }
    return res
}
// bfs
// 并查集 待练习

第7课 | 泛型递归、树的递归

1. 递归的实现、特性以及思维要点

参考链接

2. 实战题目解析:爬楼梯、括号生成等问题

实战题目

// 递归
var mp = map[int]int{}
func climbStairs(n int) int {
    if n <= 2 {
        return n
    }
    if _, ok := mp[n]; !ok {
        mp[n] = climbStairs(n - 1) + climbStairs(n - 2)
    }
    return mp[n]
}
// 动态规划
func climbStairs(n int) int {
    i, j, k := 0, 1, 0
    for m := 1; m <= n; m++ {
        k = i + j
        i, j = j, k
    }
    return k
}
func climbStairs(n int) int {
    if n <= 2 {
        return n
    }
    dp := make([]int, n + 1)
    dp[1], dp[2] = 1, 2
    for i := 3; i <= n; i++ {
        dp[i] = dp[i - 1] + dp[i - 2]
    }
    return dp[n]
}
// 矩阵
// 通项公式
// 递归
func generateParenthesis(n int) (res []string) {
    var helper func(l, r int, p string)
    helper = func(l, r int, p string) {
        if l == n && r == n {
            res = append(res, p)
            return
        }
        if l < n {
            helper(l + 1, r, p + "(")
        }
        if r < l {
            helper(l, r + 1, p + ")")
        }
    }
    helper(0, 0, "")
    return res
}
// 非递归:
type node struct {
    res string
    left int
    right int
}
func generateParenthesis(n int) []string {
    ans := []string{}
    queue := []node{}
    queue = append(queue, newNode("", n, n))
    for len(queue) > 0 {
        n :=  queue[0]
        queue = queue[1:]
        if n.left == 0 && n.right == 0 {
            ans = append(ans, n.res)
        }
        if n.left > 0 {
            queue = append(queue, newNode(n.res + "(", n.left - 1, n.right))
        }
        if n.left < n.right && n.right > 0 {
            queue = append(queue, newNode(n.res + ")", n.left, n.right - 1))
        }
    }

    return ans
}

func newNode(res string, left, right int) node {
    return node{
        res: res,
        left: left,
        right: right,
    }
}
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
// 递归
func invertTree(root *TreeNode) *TreeNode {
    if root == nil {
        return root
    }
    root.Left, root.Right = invertTree(root.Right), invertTree(root.Left)
    return root
}
// 非递归:使用队列,迭代
func invertTree(root *TreeNode) *TreeNode {
    
}
// 递归
func isValidBST(root *TreeNode) bool {
    var isValid func(root *TreeNode, min, max int) bool
    isValid = func(root *TreeNode, min, max int) bool {
        if root == nil {
            return true
        }
        if root.Val <= min || root.Val >= max {
            return false
        }
        return isValid(root.Left, min, root.Val) && isValid(root.Right, root.Val, max)
    }
    return isValid(root, math.MinInt64, math.MaxInt64)
}
// 递归中序遍历

// 迭代中序遍历

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
// 递归, dfs
func maxDepth(root *TreeNode) int {
    if root == nil {
        return 0
    }
    return max(maxDepth(root.Left), maxDepth(root.Right)) + 1
}

func max(a, b int) int {
    if a > b {
        return a
    }
    return b
}
// bfs
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
// 递归(深度优先遍历)
func minDepth(root *TreeNode) int {
    if root == nil {
        return 0
    }
    if root.Left == nil && root.Right == nil {
        return 1
    }
    ld, rd := minDepth(root.Left), minDepth(root.Right)
    if ld == 0 || rd == 0 {
        return ld + rd + 1
    }
    return min(ld, rd) + 1
}
func min(a, b int) int {
    if a < b {
        return a
    }
    return b
}
// bfs, 广度优先遍历
func minDepth(root *TreeNode) (res int) {
    if root == nil {
        return 0
    }
    queue := []*TreeNode{}
    depth := []int{}
    queue = append(queue, root)
    depth = append(depth, 1)
    for len(queue) > 0 {
        n := len(queue)
        for i := 0; i < n; i++ {
         	root := queue[0]
            level := depth[0]
            queue = queue[1:]
            depth = depth[1:]
            if root.Left == nil && root.Right == nil {
                return level
            }
            if root.Left != nil {
                queue = append(queue, root.Left)
                depth = append(depth, level + 1)
            }
            if root.Right != nil {
                queue = append(queue, root.Right)
                depth = append(depth, level + 1)
            }
        } 
    }
    return res
}
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
// 前序遍历
type Codec struct {
    
}

func Constructor() *Codec {
    return &Codec{}
}

// Serializes a tree to a single string.
func (this *Codec) serialize(root *TreeNode) string {
    sb := &strings.Builder{}
    var preorder func(root *TreeNode)
    preorder = func (root *TreeNode) {
        if root == nil {
            sb.WriteString("null,")
            return
        }
        sb.WriteString(strconv.Itoa(root.Val))
        sb.WriteByte(',')
        preorder(root.Left)
        preorder(root.Right)
    }
    preorder(root)
    return sb.String()
}

// Deserializes your encoded data to tree.
func (this *Codec) deserialize(data string) *TreeNode {    
    sp := strings.Split(data, ",")
    var decode func() *TreeNode
    decode = func() *TreeNode {
        val := sp[0]
        sp = sp[1:]
        if val == "null" {
            return nil
        }
        v, _ := strconv.Atoi(val)
        return &TreeNode{v, decode(), decode()}
    }
    return decode()
}


/**
 * Your Codec object will be instantiated and called as such:
 * ser := Constructor();
 * deser := Constructor();
 * data := ser.serialize(root);
 * ans := deser.deserialize(data);
 */

每日一课

课后作业

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
    if root == nil || p == root || q == root {
        return root
    }
    left := lowestCommonAncestor(root.Left, p, q)
    right := lowestCommonAncestor(root.Right, p, q)
    if left == nil {
        return right
    } else if right == nil {
        return left
    }
  	return root
}
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
// 递归
func buildTree(preorder []int, inorder []int) *TreeNode {
    if len(preorder) == 0 {
        return nil
    }
    root := &TreeNode{Val: preorder[0]}
    i := 0
    for ; i < len(inorder); i++ {
        if preorder[0] == inorder[i] {
            break
        }
    }
    root.Left = buildTree(preorder[1:len(inorder[:i])+1], inorder[0:i])
    root.Right = buildTree(preorder[len(inorder[:i])+1:], inorder[i+1:])
    return root
}
// 迭代
// 参考php中的写法
func combine(n int, k int) (res [][]int) {
    path := []int{}
    var bracktrack func (int)
    bracktrack = func(first int) {
        if len(path) == k {
            res = append(res, append([]int(nil), path...))
            return
        }
        for i := first; n - i + 1 >= k - len(path); i++ {
            path = append(path, i)
            bracktrack(i + 1)
            path = path[:len(path) - 1]
        }
    }
    bracktrack(1)
    return res
}
// 官方: 递归实现组合型枚举

// 官方:非递归(字典序法)实现组合型枚举


第8课 | 分治、回溯

1. 分治、回溯的实现和特性

参考链接


2. 实战题目解析:Pow(x,n)、子集

预习题目

func myPow(x float64, n int) float64 {
    if n == 0 {
        return 1
    }
    if n < 0 {
        n = -n
        x = 1 / x
    }
    p := myPow(x, n >> 1)
    if n & 1 == 0 {
        return p * p
    } else {
        return x * p * p
    }
}
// 多种写法勤加练习
// 迭代

// 递归

参考链接

3. 实战题目解析:电话号码的字母组合、N皇后

实战题目

// 分治
// hash表
// 排序
// 随机
// 官方方法五:Boyer-Moore 投票算法 重点
func majorityElement(nums []int) (ans int) {
    count := 0
    for _, num := range nums {
        if count == 0 {
            ans = num
        }
        if ans == num {
            count++
        } else {
            count--
        }
    }
    return ans
}
// dfs
// 写法一:
var mp = map[string]string{
    "2": "abc",
    "3": "edf",
    "4": "ghi",
    "5": "jkl",
    "6": "mno",
    "7": "pqrs",
    "8": "tuv",
    "9": "wxyz",
}

func letterCombinations(digits string) (res []string) {
    if digits == "" {
        return res
    }
    n := len(digits)
    var dfs func(string, int)
    dfs = func(path string, idx int){
        if idx == n {
            res = append(res, path)
            return
        }
        letters := mp[string(digits[idx])]
        for _, c := range letters {
            dfs(path + string(c), idx + 1)
        }
    }
    dfs("", 0)
    return res
}
// 写法二:dfs
var digitMap = map[byte][]byte{
	'2': {'a', 'b', 'c'},
	'3': {'d', 'e', 'f'},
	'4': {'g', 'h', 'i'},
	'5': {'j', 'k', 'l'},
	'6': {'m', 'n', 'o'},
	'7': {'p', 'q', 'r', 's'},
	'8': {'t', 'u', 'v'},
	'9': {'w', 'x', 'y', 'z'},
}

var buf []byte
var ans []string

func letterCombinations(digits string) []string {
	buf = buf[:0]
	ans = ans[:0]
	if len(digits) == 0 {
		return ans
	}
	dfs(digits, 0)
	return ans
}

func dfs(digits string, n int) {
	if n == len(digits) {
		ans = append(ans, string(buf))
		return
	}
	for _, v := range digitMap[digits[n]] {
		buf = append(buf, v)
		dfs(digits, n+1)
		buf = buf[:len(buf)-1]
	}
	return
}
// bfs, 队列迭代
func letterCombinations(digits string) (res []string) {
    if len(digits) == 0 {
        return res
    }
    res = append(res, "")
    for _, digit := range digits {
        n := len(res)
        for ; n > 0; n-- {
            m := res[0]
            res = res[1:]
            for _, d := range mp[string(digit)] {
                res = append(res, m + string(d))
            }
        }
    }
    return res
}
// 普通dfs
func solveNQueens(n int) (res [][]string) {
    pie, na, col := map[int]bool{}, map[int]bool{}, map[int]bool{}
    var dfs func(int, []int)
    dfs = func (row int, queen []int) {
        // 递归终止
        if row == n {
            ans := []string{}
            for _, c := range queen {
                r := make([]byte, 0, n)
                for i := 0; i < n; i++ {
                    if i == c {
                        r = append(r, 'Q')
                    } else {
                         r = append(r, '.')
                    }
                }
                ans = append(ans, string(r))
            }
            res = append(res, ans)
            return
        }
        for i := 0; i < n; i++ {
            if pie[i + row] || na[i - row] || col[i] {
                continue
            }
            pie[i + row] = true
            na[i - row] = true
            col[i] = true
            queen = append(queen, i)
            dfs(row + 1, queen)
            queen = queen[:len(queen) - 1]
            col[i] = false
            na[i - row] = false
            pie[i + row] = false
        }
    }
    dfs(0, []int{})
    return 
}
// 官方:位运算 dfs
var solutions [][]string

func solveNQueens(n int) [][]string {
    solutions = [][]string{}
    queens := make([]int, n)
    for i := 0; i < n; i++ {
        queens[i] = -1
    }
    solve(queens, n, 0, 0, 0, 0)
    return solutions
}

func solve(queens []int, n, row, columns, diagonals1, diagonals2 int) {
    if row == n {
        board := generateBoard(queens, n)
        solutions = append(solutions, board)
        return
    }
    availablePositions := ((1 << n) - 1) & (^(columns | diagonals1 | diagonals2))
    for availablePositions != 0 {
        position := availablePositions & (-availablePositions)
        availablePositions = availablePositions & (availablePositions - 1)
        column := bits.OnesCount(uint(position - 1))
        queens[row] = column
        solve(queens, n, row + 1, columns | position, (diagonals1 | position) >> 1, (diagonals2 | position) << 1)
        queens[row] = -1
    }
}

func generateBoard(queens []int, n int) []string {
    board := []string{}
    for i := 0; i < n; i++ {
        row := make([]byte, n)
        for j := 0; j < n; j++ {
            row[j] = '.'
        }
        row[queens[i]] = 'Q'
        board = append(board, string(row))
    }
    return board
}
// 自己写法一
func solveNQueens(n int) (res [][]string) {
    var dfs func(int, int, int, int, []int)
    dfs = func (row, pie, na, col int, picks []int) {
        // 递归终止
        if row == n {
            ans := []string{}
            for _, c := range picks {
                r := make([]byte, 0, n)
                for i := 0; i < n; i++ {
                    if c & (1 << i) > 0 {
                        r = append(r, 'Q')
                    } else {
                        r = append(r, '.')
                    }
                }
                ans = append(ans, string(r))
            }
            res = append(res, ans)
            return
        }
        // 取所有可以放的位置
        bits := (^(pie | na | col)) & (1 << n - 1) 
        for bits > 0 {
            // 取可以放的位置
            p := bits & - bits
            bits = bits & (bits - 1) // 移除最后一个1位
            picks[row] = p
            dfs(row + 1, (pie | p) << 1, (na | p) >> 1, col | p, picks)
        }
    }
    dfs(0, 0, 0 , 0, make([]int, n))
    return 
}

// 自己写法二
var ress [][]string
func solveNQueens(n int) [][]string {
    ress = [][]string{}
    dfs(n, 0, 0, 0, 0, make([]int, n))
    return ress
}

func dfs(n, row, cols, pie, na int, picks []int) {
    //处理结果
    if n <= row {
        res := make([]string, n)
        for index, col := range picks {
            str := ""
            for i := 0; i < n; i++ {
                if col & (1 << i) > 0 {
                    str += "Q"
                } else {
                    str += "."
                }
            }
            res[index] = str
        }
        ress = append(ress, res)
        return
    }
    bits := (^(cols | pie | na)) & ((1 << n) - 1) //获取所有二进制1位
    for bits > 0 {
        p := bits & -bits
        picks[row] = p;
        dfs(n, row + 1, cols | p, (pie | p) << 1, (na | p) >> 1, picks);
        bits = bits & (bits - 1);
    }
}

本周作业及下周预习

本周作业

简单

/**
 * Definition for a Node.
 * type Node struct {
 *     Val int
 *     Children []*Node
 * }
 */

func postorder(root *Node) []int {
    
}
/**
 * Definition for a Node.
 * type Node struct {
 *     Val int
 *     Children []*Node
 * }
 */

func preorder(root *Node) []int {
    
}

中等

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func preorderTraversal(root *TreeNode) []int {

}
/**
 * Definition for a Node.
 * type Node struct {
 *     Val int
 *     Children []*Node
 * }
 */

func levelOrder(root *Node) [][]int {
    
}
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
  
}
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func buildTree(preorder []int, inorder []int) *TreeNode {

}
func combine(n int, k int) [][]int {

}
func permute(nums []int) [][]int {

}
func permuteUnique(nums []int) [][]int {

}

下周预习

预习知识点

预习题目