剑指 Offer

本文是《剑指Offer》 的题解。

剑指 Offer 03. 数组中重复的数字

func findRepeatNumber(nums []int) int {
    for i := 0; i < len(nums); i++ {
        for nums[i] != i {
            if nums[nums[i]] == nums[i] {
                return nums[i]
            }

            nums[i], nums[nums[i]] = nums[nums[i]], nums[i] 
        }
    }    
    return -1
}

剑指 Offer 04. 二维数组中的查找

func findNumberIn2DArray(matrix [][]int, target int) bool {
    if len(matrix) == 0 || len(matrix[0]) == 0 {
        return false
    }

    n, m := len(matrix), len(matrix[0])
    i, j := 0, m-1
    for i < n && j >= 0 {
        if matrix[i][j] == target {
            return true
        } else if matrix[i][j] < target {
            i++
        } else {
            j--
        }
    }
    return false
}

剑指 Offer 05. 替换空格

func replaceSpace(s string) string {
    var sb strings.Builder
    for _, ch := range s {
        if ch != ' ' {
            sb.WriteRune(ch)
        } else {
            sb.WriteString("%20")
        }
    }
    return sb.String()
}

剑指 Offer 06. 从尾到头打印链表

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func reversePrint(head *ListNode) []int {
    res := []int{}
    if head == nil {
        return res
    }

    for head != nil {
        res = append(res, head.Val)
        head = head.Next
    }

    for i, j := 0, len(res)-1; i < j; i, j = i+1, j-1 {
        res[i], res[j] = res[j], res[i]
    }
    return res
}

剑指 Offer 07. 重建二叉树

/**
 * 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 || len(inorder) == 0 {
        return nil
    }

    root := &TreeNode{
        Val: preorder[0],
    }

    for pos, val := range inorder {
        if val == preorder[0] {
            root.Left = buildTree(preorder[1:1+pos], inorder[:1+pos])
            root.Right = buildTree(preorder[pos+1:], inorder[pos+1:])
        }
    }
    return root
}

剑指 Offer 09. 用两个栈实现队列

type Stack []int

func (s *Stack) Push(val int) {
    *s = append(*s, val)
}

func (s *Stack) Pop() int {
    res := (*s)[len(*s)-1]
    *s = (*s)[:len(*s)-1]
    return res
}

type CQueue struct {
    Head Stack
    Tail Stack
}


func Constructor() CQueue {
    return CQueue{}
}


func (this *CQueue) AppendTail(value int)  {
    this.Tail.Push(value)
}


func (this *CQueue) DeleteHead() int {
    if len(this.Head) == 0 {
        if len(this.Tail) == 0 {
            return -1
        }

        for len(this.Tail) != 0 {
            this.Head.Push(this.Tail.Pop())
        }
    } 
    return this.Head.Pop()
}

/**
 * Your CQueue object will be instantiated and called as such:
 * obj := Constructor();
 * obj.AppendTail(value);
 * param_2 := obj.DeleteHead();
 */

剑指 Offer 10- I. 斐波那契数列

func fib(n int) int {
    if n <= 1 {
        return n
    }

    first, second := 0, 1
    for i := 2; i <= n; i++ {
        first, second = second, (first+second)%1000000007
    }
    return second
}

剑指 Offer 10- II. 青蛙跳台阶问题

func numWays(n int) int {
    if n == 0 || n == 1 {
        return 1
    }

    first, second := 1, 1
    for i := 2; i <= n; i++ {
        first, second = second, (first+second)%1000000007
    }
    return second
}

剑指 Offer 11. 旋转数组的最小数字

func minArray(numbers []int) int {
    i, j := 0, len(numbers)-1
    for i < j {
        m := i + (j-i)/2
        // 找旋转数据最小值的,与右边界比较
        if numbers[m] < numbers[j] {
            // 最小值位于 [i, m] 之间
            j = m
        } else if numbers[m] > numbers[j] {
            // 最小值位于 [m + 1, j] 之间
            i = m + 1
        } else {
            // 不能确定,只能逐步减小范围
            j--
        }
    }
    return numbers[i]
}

剑指 Offer 12. 矩阵中的路径

var nexts = [][]int{
    {0, 1},
    {0, -1},
    {1, 0},
    {-1, 0},
}

func exist2(board [][]byte, visited [][]bool, word string, i, j int) bool {
    if len(word) == 0 {
        return true
    }

    if i < 0 || i >= len(board) || j < 0 || j >= len(board[0]) || visited[i][j] || board[i][j] != word[0] {
        return false
    }

    visited[i][j] = true
    for _, next := range nexts {
        if exist2(board, visited, word[1:], i+next[0], j+next[1]) {
            return true
        }
    }
    visited[i][j] = false
    return false
}

func exist(board [][]byte, word string) bool {
    visited := make([][]bool, len(board))
    for i := 0; i < len(board); i++ {
        visited[i] = make([]bool, len(board[0]))
    }
    for i := 0; i < len(board); i++ {
        for j := 0; j < len(board[0]); j++ {
            if exist2(board, visited, word, i, j) {
                return true
            }
        }
    }
    return false
}

剑指 Offer 13. 机器人的运动范围

var nexts = [][]int{
    {0, 1},
    {0, -1},
    {-1, 0},
    {1, 0},
}


func calNum(num int) int {
    res := 0
    for num != 0 {
        res += num%10
        num /= 10
    }
    return res
}

func dfs(board [][]int, i, j, k int) {
    if i < 0 || i >= len(board) || j < 0 || j >= len(board[0]) || board[i][j] == -1 || board[i][j] > k {
        return 
    }

    board[i][j] = -1
    for _, next := range nexts {
        dfs(board, i+next[0], j+next[1], k)
    }
}

func movingCount(m int, n int, k int) int {
    board := make([][]int, m)
    for i := 0; i < m; i++ {
        board[i] = make([]int, n)
    }

    for i := 0; i < m; i++ {
        for j := 0; j < n; j++ {
            board[i][j] = calNum(i) + calNum(j)
        }
    }

    dfs(board, 0, 0, k)
    res := 0
    for i := 0; i < m; i++ {
        for j := 0; j < n; j++ {
            if board[i][j] == -1 {
                res++
            }
        }
    }
    return res
}

剑指 Offer 14- I. 剪绳子

func max(i, j int) int {
    if i < j {
        return j
    }
    return i
}

func cuttingRope(n int) int {
    // dp[i] 表示长度为 i 的绳子剪成至少 2 段的最大乘积
    dp := make([]int, n+1)
    dp[1] = 1
    for i := 2; i <= n; i++ {
        for j := 1; j <= i/2; j++ {
            dp[i] = max(dp[i], max(dp[j]*dp[i-j], max(dp[j]*(i-j), max(j*dp[i-j], j*(i-j)))))
        }
    }
    return dp[n]
}

剑指 Offer 14- II. 剪绳子 II

func cuttingRope(n int) int {
    if n == 2 {
        return 1
    } else if n == 3 {
        return 2
    } else if n == 4 {
        return 4
    }

    // 如果绳子大于 4,尽量拆成长度为 3 的段,但是最后一段不能为 1,只能为 2/3/4
    res := 1
    for n > 4 {
        res = res * 3 % 1000000007
        n -= 3
    }
    return res * n % 1000000007;     
}

剑指 Offer 15. 二进制中1的个数

func hammingWeight(num uint32) int {
    res := 0
    for num != 0 {
        res++
        // 位计算 n&(n-1),会把该整数二进制的最右边的 1 变成 0
        num = num & (num-1)
    }
    return res
}

剑指 Offer 16. 数值的整数次方

func myPow2(x float64, n int) float64 {
    if n == 0 {
        return 1.0
    }

    if n % 2 == 0 {
        res := myPow2(x, n/2)
        return res * res
    } else {
        return x * myPow2(x, n-1)
    }
}

func myPow(x float64, n int) float64 {
    if n == 0 {
        return 1.0
    }

    if n < 0 {
        return 1.0/myPow2(x, -n)
    } else {
        return myPow2(x, n)
    }
}

剑指 Offer 17. 打印从1到最大的n位数

func printNumbers(n int) []int {
    max := int(math.Pow(10, float64(n))) - 1
    res := make([]int, max-1)
    for i := 1; i < max; i++ {
        res[i-1] = i
    } 
    return res
}

剑指 Offer 18. 删除链表的节点

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func deleteNode(head *ListNode, val int) *ListNode {
    if head == nil {
        return nil
    }

    if head.Val == val {
        return head.Next
    }

    slow, fast := head, head.Next
    for fast != nil {
        if fast.Val == val {
            slow.Next = fast.Next
            break
        }
        slow, fast = slow.Next, fast.Next
    }
    return head
}

剑指 Offer 19. 正则表达式匹配

func isMatch2(s, p string, i, j int) bool {
    if j == len(p) {
        return i == len(s)
    }

    if i == len(s) {
        if (len(p)-j)%2 != 0 {
            return false
        }

        j++
        for ; j < len(p);  {
            if p[j] != '*' {
                return false
            }
            j += 2
        }
        return true
    }

    flag := false
    if j+1 < len(p) && p[j+1] == '*' {
        if s[i] == p[j] || p[j] == '.' {
            flag = isMatch2(s, p, i, j+2) || isMatch2(s, p, i+1, j)
        } else {
            flag = isMatch2(s, p, i, j+2)
        }
    } else {
        if s[i] == p[j] || p[j] == '.' {
            flag = isMatch2(s, p, i+1, j+1)
        } else {
            flag = false
        }
    }
    return flag
}

func isMatch(s string, p string) bool {
    return isMatch2(s, p, 0, 0)
}

剑指 Offer 20. 表示数值的字符串

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

    i := 0
    if s[i] == '+' || s[i] == '-' {
        i++
    }

    if len(s)-i < 2 {
        return false
    } 

    isDot := false
    for i < len(s) {
        if s[i] == '.' {
            if isDot {
                return false
            }
            isDot = true
        } else if !unicode.IsDigit(rune(s[i])) {
            return false
        }
        i++
    }
    return true
} 

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

    i := 0
    if s[i] == '+' || s[i] == '-' {
        i++
    }

    if i == len(s) {
        return false
    }

    for i < len(s) {
        if !unicode.IsDigit(rune(s[i])) {
            return false
        }
        i++
    }
    return true
}

func isNumber(s string) bool {
    s = strings.TrimSpace(s)
    if len(s) == 0 {
        return false
    }

    isE, pos := false, 0
    for i := 0; i < len(s); i++ {
        if s[i] == 'e' || s[i] == 'E' {
            if isE {
                return false
            }
            isE, pos = true, i
        }
    }

    if isE {
        return (isFloat(s[:pos]) || isInteger(s[:pos])) && isInteger(s[pos+1:])
    } else {
        return isFloat(s) || isInteger(s)
    }
}

剑指 Offer 21. 调整数组顺序使奇数位于偶数前面

func exchange(nums []int) []int {
    i, j := 0, len(nums)
    for i < j {
        if nums[i]%2 != 0 {
            i++
        } else {
            j--
            nums[i], nums[j] = nums[j], nums[i]
        }
    }
    return nums
}

剑指 Offer 22. 链表中倒数第k个节点

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func getKthFromEnd(head *ListNode, k int) *ListNode {
    if head == nil {
        return head
    }

    slow, fast := head, head
    for k > 0 {
        fast = fast.Next
        k--
    }

    for fast != nil {
        slow, fast = slow.Next, fast.Next
    }

    return slow
}

剑指 Offer 24. 反转链表

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func reverseList(head *ListNode) *ListNode {
    if head == nil || head.Next == nil {
        return head
    }

    var pre, cur, next *ListNode = nil, head, head
    for cur != nil {
        next = cur.Next
        cur.Next = pre
        pre, cur = cur, next
    }
    return pre
}

剑指 Offer 25. 合并两个排序的链表

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func mergeTwoLists(l1 *ListNode, l2 *ListNode) *ListNode {
    newHead := &ListNode{Val:-1}
    node := newHead
    for l1 != nil && l2 != nil {
        if l1.Val <= l2.Val {   
            node.Next = l1
            l1 = l1.Next
        } else {
            node.Next = l2
            l2 = l2.Next
        }
        node = node.Next
    }

    if l1 != nil {
        node.Next = l1
    } else {
        node.Next = l2
    }

    return newHead.Next
}

剑指 Offer 26. 树的子结构

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func isEqual(A *TreeNode, B *TreeNode) bool {
    if B == nil {
        return true
    }

    if A == nil || A.Val != B.Val {
        return false
    }

    return isEqual(A.Left, B.Left) && isEqual(A.Right, B.Right)
}

func isSubStructure(A *TreeNode, B *TreeNode) bool {
    if A == nil || B == nil {
        return false
    }

    if A.Val == B.Val && isEqual(A, B) {
        return true
    }

    return isSubStructure(A.Left, B) || isSubStructure(A.Right, B)
}

剑指 Offer 27. 二叉树的镜像

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func mirrorTree(root *TreeNode) *TreeNode {
    if root == nil {
        return root
    }

    root.Left, root.Right = root.Right, root.Left
    mirrorTree(root.Left)
    mirrorTree(root.Right)
    return root
}

剑指 Offer 28. 对称的二叉树

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func isSymmetric2(root1, root2 *TreeNode) bool {
    if root1 == nil && root2 == nil {
        return true
    }

    if root1 == nil || root2 == nil || root1.Val != root2.Val {
        return false
    }

    return isSymmetric2(root1.Left, root2.Right) && isSymmetric2(root1.Right, root2.Left)
}


func isSymmetric(root *TreeNode) bool {
    if root == nil {
        return true
    }

    return isSymmetric2(root.Left, root.Right)
}

剑指 Offer 29. 顺时针打印矩阵

func print(matrix [][]int, i1, j1, i2, j2 int) []int {
    var res []int
    if i1 == i2 {
        for j := j1; j <= j2; j++ {
            res = append(res, matrix[i1][j])
        }
        return res
    }

    if j1 == j2 {
        for i := i1; i <= i2; i++ {
            res = append(res, matrix[i][j1])
        }
        return res
    }

    for j := j1; j <= j2; j++ {
        res = append(res, matrix[i1][j])
    }

    for i := i1+1; i < i2; i++ {
        res = append(res, matrix[i][j2])
    }

    for j := j2; j >= j1; j-- {
        res = append(res, matrix[i2][j])
    }

    for i := i2-1; i > i1; i-- {
        res = append(res, matrix[i][j1])
    }
    return res
}

func spiralOrder(matrix [][]int) []int {
    var res []int
    if len(matrix) == 0 || len(matrix[0]) == 0 {
        return res
    }

    i1, j1, i2, j2 := 0, 0, len(matrix)-1, len(matrix[0])-1
    for i1 <= i2 && j1 <= j2 {
        res = append(res, print(matrix, i1, j1, i2, j2)...)
        i1++
        i2--
        j1++
        j2--
    }
    return res
}

剑指 Offer 30. 包含min函数的栈

type Stack []int

func (s *Stack) Push(val int) {
    *s = append(*s, val)
}

func (s *Stack) Pop() int {
    res := (*s)[len(*s)-1]
    *s = (*s)[:len(*s)-1]
    return res
}

func (s *Stack) Peek() int {
    return (*s)[len(*s)-1]
}

func min(a, b int) int {
    if a > b {
        return b
    }
    return a
}

type MinStack struct {
    data Stack
    min  Stack
}


/** initialize your data structure here. */
func Constructor() MinStack {
    return MinStack{}
}


func (this *MinStack) Push(x int)  {
    this.data.Push(x)
    if len(this.min) == 0 {
        this.min.Push(x)
    } else {
        this.min.Push(min(this.min.Peek(), x))
    }
}


func (this *MinStack) Pop()  {
    this.data.Pop()
    this.min.Pop()
}


func (this *MinStack) Top() int {
    return this.data.Peek()
}


func (this *MinStack) Min() int {
    return this.min.Peek()
}


/**
 * Your MinStack object will be instantiated and called as such:
 * obj := Constructor();
 * obj.Push(x);
 * obj.Pop();
 * param_3 := obj.Top();
 * param_4 := obj.Min();
 */

剑指 Offer 31. 栈的压入、弹出序列

func validateStackSequences(pushed []int, popped []int) bool {
    if len(pushed) != len(popped) {
        return false
    }

    var stack []int
    j := 0
    for i := 0; i < len(pushed); i++ {
        stack = append(stack, pushed[i])
        for len(stack) != 0 && stack[len(stack)-1] == popped[j] {
            stack = stack[:len(stack)-1]
            j++
        }
    } 

    return len(stack) == 0
}

剑指 Offer 32 - I. 从上到下打印二叉树

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

    var queue []*TreeNode
    queue = append(queue, root)
    for len(queue) != 0 {
        size := len(queue)
        for i := 0; i < size; i++ {
            node := queue[i]
            res = append(res, node.Val)
            if node.Left != nil {
                queue = append(queue, node.Left)
            }
            if node.Right != nil {
                queue = append(queue, node.Right)
            }
        }
        queue = queue[size:]
    }
    return res
}

剑指 Offer 32 - II. 从上到下打印二叉树 II

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

    var queue []*TreeNode
    queue = append(queue, root)
    for len(queue) != 0 {
        size := len(queue)
        var list []int
        for i := 0; i < size; i++ {
            node := queue[i]
            list = append(list, node.Val)
            if node.Left != nil {
                queue = append(queue, node.Left)
            }

            if node.Right != nil {
                queue = append(queue, node.Right)
            }
        }
        queue = queue[size:]
        res = append(res, list)
    }
    return res
}

剑指 Offer 32 - III. 从上到下打印二叉树 III

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

    var queue []*TreeNode
    queue = append(queue, root)
    flag := true
    for len(queue) != 0 {
        size := len(queue)
        list := make([]int, size)
        for i := 0; i < size; i++ {
            node := queue[i]
            if flag {
                list[i] = node.Val
            } else {
                list[size-1-i] = node.Val
            }

            if node.Left != nil {
                queue = append(queue, node.Left)
            }

            if node.Right != nil {
                queue = append(queue, node.Right)
            }
        }
        queue = queue[size:]
        res = append(res, list)
        flag = !flag
    }
    return res
}

剑指 Offer 33. 二叉搜索树的后序遍历序列

func verifyPostorder(postorder []int) bool {
    if len(postorder) == 0 {
        return true
    }

    root := postorder[len(postorder)-1]
    i, pos := 0, 0
    for postorder[i] < root {
        i++
    }
    pos = i

    for i < len(postorder)-1 {
        if postorder[i] <= root {
            return false
        }
        i++
    }

    return verifyPostorder(postorder[:pos]) && verifyPostorder(postorder[pos:len(postorder)-1])
}

剑指 Offer 34. 二叉树中和为某一值的路径

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func pathSum2(root *TreeNode, target int, path *[]int, res *[][]int) {
    if root == nil {
        return
    }

    target -= root.Val
    *path = append(*path, root.Val)
    if root.Left == nil && root.Right == nil && target == 0 {
        temp := make([]int, len(*path))
        copy(temp, *path)
        *res = append(*res, temp)
    }
    
    pathSum2(root.Left, target, path, res)
    pathSum2(root.Right, target, path, res)
    *path = (*path)[:len(*path)-1]
}

func pathSum(root *TreeNode, target int) [][]int {
    var res [][]int
    if root == nil {
        return res
    }

    var path []int
    pathSum2(root, target, &path, &res)
    return res
}

剑指 Offer 35. 复杂链表的复制

/**
 * Definition for a Node.
 * type Node struct {
 *     Val int
 *     Next *Node
 *     Random *Node
 * }
 */

func copyRandomList(head *Node) *Node {
    node := head
    for node != nil {
        next := node.Next
        node.Next = &Node{Val:node.Val}
        node.Next.Next = next
        node = node.Next.Next
    }

    node = head
    for node != nil {
        if node.Random != nil {
            node.Next.Random = node.Random.Next
        }
        node = node.Next.Next
    }

    newHead1, newHead2 := &Node{Val:-1}, &Node{Val:-1}
    node1, node2, node := newHead1, newHead2, head
    for node != nil {
        node1.Next, node2.Next = node, node.Next
        node1, node2 = node1.Next, node2.Next
        node = node.Next.Next
    }
    node1.Next = nil
    return newHead2.Next
}

剑指 Offer 38. 字符串的排列

func permutation2(sBytes []byte, visited []bool, path *[]byte, res *[]string) {
    if len(*path) == len(sBytes) {
        *res = append(*res, string(*path))
        return 
    }

    for i := 0; i < len(sBytes); i++ {
        if visited[i] {
            continue
        }

        if i >= 1 && sBytes[i-1] == sBytes[i] && !visited[i-1] {
            continue
        }
        *path = append(*path, sBytes[i])
        visited[i] = true
        permutation2(sBytes, visited, path, res)
        visited[i] = false
        *path = (*path)[:len(*path)-1]
    }
}

func permutation(s string) []string {
    var res []string
    if len(s) == 0 {
        return res
    }
    sBytes := []byte(s)
    sort.Slice(sBytes, func(i, j int) bool {
        return sBytes[i] < sBytes[j]
    })

    visited := make([]bool, len(s))
    var path []byte
    permutation2(sBytes, visited, &path, &res)
    return res
}

剑指 Offer 39. 数组中出现次数超过一半的数字

func majorityElement(nums []int) int {
    // Boyer-Moore 投票算法
    res, cnt := 0, 0
    for _, num := range nums {
        if cnt == 0 {
            res, cnt = num, 1
        } else if num == res {
            cnt++
        } else {
            cnt--
        }
    }
    return res
}

剑指 Offer 40. 最小的k个数

func quickSort(arr []int, i, j, k int) {
    if i < j {
        m := sort(arr, i, j)
        if m < k {
            quickSort(arr, m+1, j, k)
        } else if m > k {
            quickSort(arr, i, m-1, k)
        }
    }
}

func sort(arr []int, i, j int) int {
    // 将第一个数作为 target,先右边再左边
    start, target := i, arr[i]
    for i < j {
        // 右边是大于 target 的数
        for i < j && arr[j] > target {
            j--
        }
        
        // 左边是小于等于 target 的数
        for i < j && arr[i] <= target {
            i++
        }

        arr[i], arr[j] = arr[j], arr[i]
    }

    arr[start], arr[i] = arr[i], arr[start]
    return i
}

func getLeastNumbers(arr []int, k int) []int {
    // 使用快速排序
    quickSort(arr, 0, len(arr)-1, k-1)
    return arr[:k]
}

剑指 Offer 41. 数据流中的中位数

type minHeap []int

func (h minHeap) Len() int {
    return len(h)
}

func (h minHeap) Swap(i, j int) {
    h[i], h[j] = h[j], h[i]
}

func (h minHeap) Less(i, j int) bool {
    return h[i] < h[j]
}

func (h *minHeap) Push(x interface{}) {
    *h = append(*h, x.(int))
}

func (h *minHeap) Pop() interface{} {
    x := (*h)[len(*h)-1]
    *h = (*h)[:len(*h)-1]
    return x
}

type maxHeap []int

func (h maxHeap) Len() int {
    return len(h)
}

func (h maxHeap) Swap(i, j int) {
    h[i], h[j] = h[j], h[i]
}

func (h maxHeap) Less(i, j int) bool {
    return h[i] > h[j]
}

func (h *maxHeap) Push(x interface{}) {
    *h = append(*h, x.(int))
}

func (h *maxHeap) Pop() interface{} {
    x := (*h)[len(*h)-1]
    *h = (*h)[:len(*h)-1]
    return x
}

type MedianFinder struct {
    // left 是大顶堆,right 是小顶堆
    left maxHeap
    right minHeap
}

/** initialize your data structure here. */
func Constructor() MedianFinder {
    return MedianFinder{}
}

func (this *MedianFinder) AddNum(num int)  {
    if len(this.left) == len(this.right) {
        heap.Push(&this.right, num)
        heap.Push(&this.left, heap.Pop(&this.right))
    } else {
        heap.Push(&this.left, num)
        heap.Push(&this.right, heap.Pop(&this.left))
    }
}

func (this *MedianFinder) FindMedian() float64 {
    if len(this.left) == len(this.right) {
        num1, num2 := this.left[0], this.right[0]
        return float64(num1+num2) / 2.0
    } else {
        return float64(this.left[0])
    }
}
/**
 * Your MedianFinder object will be instantiated and called as such:
 * obj := Constructor();
 * obj.AddNum(num);
 * param_2 := obj.FindMedian();
 */

剑指 Offer 42. 连续子数组的最大和

func max(a, b int) int {
    if a > b {
        return a
    }
    return b
}

func maxSubArray(nums []int) int {
    // dp[i]:以 nums[i] 结尾的连续子数组的最大和
    dp := make([]int, len(nums))
    dp[0] = nums[0]

    res := dp[0]
    for i := 1; i < len(nums); i++ {
        dp[i] = max(dp[i-1]+nums[i], nums[i])
        res = max(res, dp[i])
    }
    return res
}

剑指 Offer 43. 1~n 整数中 1 出现的次数

func countDigitOne(n int) int {
    if n == 0 {
        return 0
    }

    s := strconv.Itoa(n)
    high := int(s[0] - '0')
    pow := int(math.Pow(10, float64(len(s)-1)))
    last := n - pow*high

    if high == 1 {
        // 例如:1234,拆为 1-999 和 1000-1234 两部分: 
        //      countDigitOne(pow - 1):1-999 出现 1 的次数
        //      last + 1: 1000-1234 千位上出现 1 的次数
        //      countDigitOne(last):1000-1234 除千位外出现 1 的次数
        return countDigitOne(pow-1) + last + 1 + countDigitOne(last)
    } else {
        // 例如:3234,拆为 1-999、1000-2999 和 3000-3234 三部分:
        //      countDigitOne(pow - 1):1-999 出现 1 的次数
        //      pow:1000-2999:千位上出现 1 的次数
        //      countDigitOne(pow - 1) * (high - 1):1000-2999 除千位外出现 1 的次数    
        //      countDigitOne(last):3000-3234 出现 1 的次数
        return countDigitOne(pow-1)*high + pow + countDigitOne(last)        
    }
}

剑指 Offer 44. 数字序列中某一位的数字

func findNthDigit(n int) int {
    if n == 0 {
        return 0
    }

    // length 是数字的字符长度,base 是基数,cnt 为长度为 length 的数字数目
    // 例如:10-99 之间的数字,len 为 2,base 为 10,cnt 为 90
    length, base := 1, 1
    cnt := length * 9 * base
    for n-cnt > 0 {
        n -= cnt
        length++
        base *= 10
        cnt = length * 9 * base
    }

    num := base + n/length
    if n%length == 0 {
        s := strconv.Itoa(num - 1)
        return int(s[len(s)-1] - '0')
    } else {
        s := strconv.Itoa(num)
        return int(s[n%length-1] - '0')
    }
}

剑指 Offer 45. 把数组排成最小的数

func minNumber(nums []int) string {
    ss := make([]string, len(nums))
    for i, num := range nums {
        ss[i] = strconv.Itoa(num)
    }

    sort.Slice(ss, func(i, j int) bool{
        return ss[i]+ss[j] < ss[j]+ss[i]
    })

    var sb strings.Builder
    for _, s := range ss {
        sb.WriteString(s)
    }
    return sb.String()
}

剑指 Offer 46. 把数字翻译成字符串

func translateNum(num int) int {
    s := strconv.Itoa(num)
    // dp[i]:s[:i] 所能组成的翻译方法数
    dp := make([]int, len(s))
    dp[0] = 1
    for i := 1; i < len(s); i++ {
        dp[i] = dp[i-1]
        if s[i-1] == '1' || (s[i-1] == '2' && '0' <= s[i] && s[i] <= '5') {
            if i >= 2 {
                dp[i] += dp[i-2]
            } else {
                dp[i] += 1
            }
        }
    }
    return dp[len(s)-1]
}

剑指 Offer 47. 礼物的最大价值

func max(a, b int) int {
    if a > b {
        return a
    }
    return b
}

func maxValue(grid [][]int) int {
    res := 0
    m, n := len(grid), len(grid[0])
    dp := make([][]int, m)
    for i := 0; i < m; i++ {
        dp[i] = make([]int, n)
    }

    res, dp[0][0] = grid[0][0], grid[0][0]
    for j := 1; j < n; j++ {
        dp[0][j] = dp[0][j-1] + grid[0][j] 
        res = max(res, dp[0][j])
    }
    for i := 1; i < m; i++ {
        dp[i][0] = dp[i-1][0] + grid[i][0]
        res = max(res, dp[i][0])
    }

    for i := 1; i < m; i++ {
        for j := 1; j < n; j++ {
            dp[i][j] = max(dp[i-1][j], dp[i][j-1]) + grid[i][j]
            res = max(res, dp[i][j])
        }
    }
    return res
}

剑指 Offer 48. 最长不含重复字符的子字符串

func max(a, b int) int {
    if a > b {
        return a
    }
    return b
}

func lengthOfLongestSubstring(s string) int {
    // 存储字符在字符串中的位置
    hashMap := make(map[byte]int)
    i, res := 0, 0
    for j := 0; j < len(s); j++ {
        if pos, ok := hashMap[s[j]]; ok {
            i = max(i, pos+1)
        }
        hashMap[s[j]] = j
        res = max(res, j-i+1)
    }
    return res
}

剑指 Offer 49. 丑数

func min(a, b int) int {
    if a < b {
        return a
    }
    return b
}

func nthUglyNumber(n int) int {
    // dp[i]:第 i 个丑数
    dp := make([]int, n+1)
    dp[1] = 1
    i2, i3, i5 := 1, 1, 1
    for i := 2; i <= n; i++ {
        dp[i] = min(dp[i2]*2, min(dp[i3]*3, dp[i5]*5))
        for dp[i2]*2 <= dp[i] {
            i2++
        }
        for dp[i3]*3 <= dp[i] {
            i3++
        }
        for dp[i5]*5 <= dp[i] {
            i5++
        }
    }
    return dp[n]
}

剑指 Offer 50. 第一个只出现一次的字符

func firstUniqChar(s string) byte {
    cnts := make([]int, 26)
    for _, ch := range s {
        cnts[int(ch-'a')]++
    }

    for _, ch := range s {
        if cnts[int(ch-'a')] == 1 {
            return byte(ch)
        }
    }
    return ' '
}

剑指 Offer 51. 数组中的逆序对

var res int

func sort(nums, temp []int, i, j int) {
    if i < j {
        m := i + (j-i)/2
        sort(nums, temp, i, m)
        sort(nums, temp, m+1, j)
        merge(nums, temp, i, m, j)
    }
}

func merge(nums, temp []int, i, m, j int) {
    pos, i1, i2 := i, i, m+1
    for i1 <= m && i2 <= j {
        if nums[i1] <= nums[i2] {
            temp[pos] = nums[i1]
            res += i2 - m - 1
            i1++
        } else {
            temp[pos] = nums[i2] 
            i2++
        }
        pos++
    }

    if i1 <= m {
        copy(temp[pos:j+1], nums[i1:m+1])
        res += (m-i1+1) * (j-m)
    }

    if i2 <= j {
        copy(temp[pos:j+1], nums[i2:j+1])
    }

    copy(nums[i:j+1], temp[i:j+1])
}

func reversePairs(nums []int) int {
    res = 0
    // 使用归并排序
    sort(nums, make([]int, len(nums)), 0, len(nums)-1)
    return res
}

剑指 Offer 52. 两个链表的第一个公共节点

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func getIntersectionNode(headA, headB *ListNode) *ListNode {
    if headA == nil || headB == nil {
        return nil
    }

    node1, node2 := headA, headB
    flag := false
    for node1 != node2 {
        node1 = node1.Next
        if node1 == nil {
            if flag {
                return nil
            }
            flag, node1 = true, headB
        }

        node2 = node2.Next
        if node2 == nil {
            node2 = headA
        }
    }
    return node1
}

剑指 Offer 53 - I. 在排序数组中查找数字 I

func searchLeft(nums []int, target int) int {
    i, j := 0, len(nums)-1
    for i <= j {
        m := i + (j-i)/2
        if nums[m] > target {
            j = m - 1
        } else if nums[m] < target {
            i = m + 1
        } else {
            j = m - 1
        }
    }

    if i >= len(nums) || nums[i] != target {
        return -1
    }
    return i
}

func searchRight(nums []int, target int) int {
    i, j := 0, len(nums)-1
    for i <= j {
        m := i + (j-i)/2
        if nums[m] > target {
            j = m - 1
        } else if nums[m] < target {
            i = m + 1
        } else {
            i = m + 1
        }
    }

    if j < 0 || nums[j] != target {
        return -1
    }
    return j
}

func search(nums []int, target int) int {
    left := searchLeft(nums, target)
    if left == -1 {
        return 0
    } 
    right := searchRight(nums, target) 
    return right - left + 1
}

剑指 Offer 53 - II. 0~n-1中缺失的数字

func missingNumber(nums []int) int {
    res := 0
    for _, num := range nums {
        res ^= num
    }

    for i := 0; i <= len(nums); i++ {
        res ^= i
    }
    return res
}

剑指 Offer 54. 二叉搜索树的第k大节点

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
var kVal, res int

func kthLargest2(root *TreeNode) bool {
    if root == nil {
        return false
    }

    if kthLargest2(root.Right) {
        return true
    }
    kVal--
    if kVal == 0 {
        res = root.Val
        return true
    }
    if kthLargest2(root.Left) {
        return true
    }
    return false
} 

func kthLargest(root *TreeNode, k int) int {
    kVal, res = k, 0
    kthLargest2(root)
    return res
}

剑指 Offer 55 - I. 二叉树的深度

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func max(a, b int) int {
    if a > b {
        return a
    }
    return b
}

func maxDepth(root *TreeNode) int {
    if root == nil {
        return 0
    }

    left, right := maxDepth(root.Left), maxDepth(root.Right)
    return max(left, right) + 1
}

剑指 Offer 55 - II. 平衡二叉树

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func max(a, b int) int {
    if a > b {
        return a
    }
    return b
}

func maxDepth(root *TreeNode) int {
    if root == nil {
        return 0
    }

    left, right := maxDepth(root.Left), maxDepth(root.Right)
    return max(left, right) + 1
}

func isBalanced(root *TreeNode) bool {
    if root == nil {
        return true
    }

    left, right := maxDepth(root.Left), maxDepth(root.Right)
    if math.Abs(float64(left-right)) > 1.0 {
        return false
    }
    return isBalanced(root.Left) && isBalanced(root.Right)
}

剑指 Offer 56 - I. 数组中数字出现的次数

func singleNumbers(nums []int) []int {
    num := 0
    for i := 0; i < len(nums); i++ {
        num ^= nums[i]
    }

    // num & -num 会获得 num 的位级表示中最低的那一位 1
    // 例如:num 为 10110100,-num 为 ~num + 1 = 01001100,num & -num 为 00000100
    num &= -num
    res := make([]int, 2)
    for i := 0; i < len(nums); i++ {
        if num & nums[i] == 0 {
            res[0] ^= nums[i]
        } else {
            res[1] ^= nums[i]
        }
    }
    return res
}

剑指 Offer 56 - II. 数组中数字出现的次数 II

func singleNumber(nums []int) int {
    res := 0
    for i := 0; i < 32; i++ {
        cnt := 0
        // 统计所有数字的二进制在第 i 位上 1 的数字
        for _, num := range nums {
            cnt += (num >> i) & 1
        }
        res |= (cnt % 3) << i
    }
    return res
}

剑指 Offer 57. 和为s的两个数字

func twoSum(nums []int, target int) []int {
    i, j := 0, len(nums)-1
    for i < j {
        sum := nums[i] + nums[j]
        if sum == target {
            return []int{nums[i], nums[j]}
        } else if sum < target {
            i++
        } else {
            j--
        }
    }
    return []int{}
}

剑指 Offer 57 - II. 和为s的连续正数序列

func findContinuousSequence(target int) [][]int {
    var res [][]int
    if target <= 2 {
        return res
    }

    i, j, sum := 1, 2, 3
    for i < j {
        if sum == target {
            list := make([]int, j-i+1)
            for k := i; k <= j; k++ {
                list[k-i] = k
            }
            res = append(res, list)
            sum -= i
            i++
            j++
            sum += j
        } else if sum < target {
            j++
            sum += j
        } else {
            sum -= i
            i++
        }
    }
    return res
}

剑指 Offer 58 - I. 翻转单词顺序

func reverseWords(s string) string {
    ss := strings.Fields(s)
    for i, j := 0, len(ss)-1; i < j; i, j = i+1, j-1 {
        ss[i], ss[j] = ss[j], ss[i]
    }
    return strings.Join(ss, " ")
}

剑指 Offer 58 - II. 左旋转字符串

// 方式一
func reverseLeftWords(s string, n int) string {
    return s[n:] + s[:n]
}
// 方式二
func reverse(b []byte, i, j int) {
    for i < j {
        b[i], b[j] = b[j], b[i]
        i++
        j--
    }
}

func reverseLeftWords(s string, n int) string {
    b := []byte(s)
    reverse(b, 0, n-1)
    reverse(b, n, len(b)-1)
    reverse(b, 0, len(b)-1)
    return string(b)
}

剑指 Offer 59 - I. 滑动窗口的最大值

func offer(deque *[]int, val int) {
    for len(*deque) != 0 && (*deque)[len(*deque)-1] < val {
        *deque = (*deque)[:len(*deque)-1]
    }
    *deque = append(*deque, val)
}

func maxSlidingWindow(nums []int, k int) []int {
    var res, deque []int

    for i := 0; i < len(nums); i++ {
        if i < k {
            offer(&deque, nums[i])
            if i == k-1 {
                res = append(res, deque[0])
            }
        } else {
            if deque[0] == nums[i-k] {
                deque = deque[1:]
            }
            offer(&deque, nums[i])
            res = append(res, deque[0])
        }
    }
    return res
}

剑指 Offer 59 - II. 队列的最大值

type MaxQueue struct {
    data []int
    max  []int
}

func Constructor() MaxQueue {
    return MaxQueue{}
}

func (this *MaxQueue) Max_value() int {
    if len(this.max) == 0 {
        return -1
    }
    return this.max[0]
}

func (this *MaxQueue) Push_back(value int)  {
    this.data = append(this.data, value)
    for len(this.max) != 0 && this.max[len(this.max)-1] < value {
        this.max = this.max[:len(this.max)-1]
    }
    this.max = append(this.max, value)
}

func (this *MaxQueue) Pop_front() int {
    if len(this.data) == 0 {
        return -1
    }

    res := this.data[0]
    this.data = this.data[1:]
    if res == this.max[0] {
        this.max = this.max[1:]
    }
    return res
}
/**
 * Your MaxQueue object will be instantiated and called as such:
 * obj := Constructor();
 * param_1 := obj.Max_value();
 * obj.Push_back(value);
 * param_3 := obj.Pop_front();
 */

剑指 Offer 60. n个骰子的点数

func dicesProbability(n int) []float64 {
    // dp[i][j]:i 个骰子掷到分数 j 的出现次数
    dp := make([][]int, n+1)
    for i := 0; i <= n; i++ {
        dp[i] = make([]int, 6*n+1)
    }
    for j := 1; j <= 6; j++ {
        dp[1][j] = 1
    }
    for i := 2; i <= n; i++ {
        for j := i; j <= i*6; j++ {
            for k := 1; k <= 6 && j > k; k++ {
                dp[i][j] += dp[i-1][j-k]
            }
        }
    }

    sum := math.Pow(6, float64(n))
    res := make([]float64, 5*n+1)
    for j := n; j <= n*6; j++ {
        res[j-n] = float64(dp[n][j]) / float64(sum)
    }
    return res
}

剑指 Offer 61. 扑克牌中的顺子

func isStraight(nums []int) bool {
    sort.Ints(nums)
    i, cnt := 0, 0
    for i < len(nums) && nums[i] == 0 {
        cnt++
        i++
    }

    for i+1 < len(nums) {
        if nums[i+1] == nums[i] {
            return false
        }
        cnt -= nums[i+1] - nums[i] - 1
        if cnt < 0 {
            return false
        }
        i++
    }
    return true
}

剑指 Offer 62. 圆圈中最后剩下的数字

func lastRemaining(n int, m int) int {
    if n == 1 {
        return 0
    }

    res := 0
    for i := 2; i <= n; i++ {
        res = (res + m) % i
    }
    return res
}

剑指 Offer 63. 股票的最大利润

func max(a, b int) int {
    if a > b {
        return a
    }
    return b
}

func maxProfit(prices []int) int {
    if len(prices) == 0 {
        return 0
    }
    // dp[i][0]:第 i+1 天,手里没有股票,所能获得的最大利润
    // dp[i][1]:第 i+1 天,手里有股票,所能获得的最大利润
    dp := make([][2]int, len(prices))
    dp[0][1] = -prices[0]

    for i := 1; i < len(prices); i++ {
        dp[i][0] = max(dp[i-1][0], dp[i-1][1] + prices[i])
        dp[i][1] = max(dp[i-1][1], -prices[i])
    }
    return dp[len(prices)-1][0]
}

剑指 Offer 64. 求1+2+…+n

var res int

func dfs(n int) bool {
    res += n
    return n > 0 && dfs(n-1)
}

func sumNums(n int) int {
    res = 0
    dfs(n)
    return res 
}

剑指 Offer 65. 不用加减乘除做加法

func add(a int, b int) int {
    if a == 0 {
        return b
    }
    return add((a&b)<<1, a^b)
}   

剑指 Offer 66. 构建乘积数组

func constructArr(a []int) []int {
    res := make([]int, len(a))
    temp := 1
    for i := 0; i < len(a); i++ {
        res[i] = temp
        temp *= a[i]
    }

    temp = 1
    for i := len(a)-1; i >= 0; i-- {
        res[i] *= temp
        temp *= a[i]
    }
    return res
}

剑指 Offer 67. 把字符串转换成整数

func strToInt(str string) int {
    str = strings.TrimSpace(str)
    if len(str) == 0 {
        return 0
    }
    i := 0
    var sign byte = '+'
    if str[i] == '+' || str[i] == '-' {
        sign = str[i]
        i++
    }

    num := 0
    for i < len(str) && unicode.IsDigit(rune(str[i])) {
        num = num*10 + int(str[i] - '0')
        if sign == '+' && num >= math.MaxInt32 {
            return math.MaxInt32
        } else if sign == '-' && -num <= math.MinInt32 {
            return math.MinInt32
        }
        i++ 
    }

    if sign == '+' {
        return num
    } else {
        return -num
    }
}

剑指 Offer 68 - II. 二叉树的最近公共祖先

/**
 * 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 || root == p || root == q {
        return root
    }

    left := lowestCommonAncestor(root.Left, p, q)
    right := lowestCommonAncestor(root.Right, p, q)

    if left != nil && right != nil {
        return root
    }

    if left == nil {
        return right
    } else {
        return left
    }
}
posted @ 2022-06-04 15:54  呵呵233  阅读(45)  评论(0编辑  收藏  举报