Contents

Leetcode Practice

Contents

Array

👉 LeetCode

func search(nums []int, target int) int {
    left, right := 0, len(nums)-1
    for left <= right{
        mid := right - left) >> 1 + left
        if nums[mid] == target{
            return mid
        }else if nums[mid] < target {
            left = mid + 1
        }else{
            right = mid - 1
        }
    }
   return -1
}

Find The Single Number

Example 1
input: nums = [2,2,3,3,4]
output: 4


Example 2
input: nums = [2,2,3,3,5,7,7,8,8]
output: 5


nums.length >= 3

func solution(nums []int) int {
    if len(nums) < 3 {
        return -1
    }
    left, right := 0, len(nums)-1
    for left+3 < right {
        mid := left + (right-left)>>1
        if mid%2 == 1 {
            if nums[mid] == nums[mid+1] {
                right = mid - 1
            } else if nums[mid] == nums[mid-1] {
                left = mid + 1
            } else {
                return nums[mid]
            }
        } else {
            if nums[mid] == nums[mid-1] {
                right = mid - 2
            } else if nums[mid] == nums[mid+1] {
                left = mid + 2
            } else {
                return nums[mid]
            }
        }
    }

    if left == 0 {
        return nums[left]
    }
    if right == len(nums)-1 {
        return nums[right]
    }

    return -1
}

34. Find First and Last Position of Element in Sorted Array

👉 LeetCode

func searchRange(nums []int, target int) []int {
    res := []int{-1, -1}
    if len(nums) == 0{
        return res
    }
    left, right := 0, len(nums) - 1
    for left <= right{
        mid := left + (right-left)>>1
        if nums[mid] >= target{
            right = mid - 1
        } else {
            left = mid + 1
        }
    }
    // 5 7 7      8    8 10
    //     right  left
    if left <= len(nums) - 1 && nums[left] == target{
        res[0] = left
    }

    left, right = 0, len(nums) - 1
    for left <= right{
        mid := left + (right-left)>>1
        if nums[mid] <= target{
            left = mid + 1
        }else {
            right = mid - 1
        }
    }
    // 5 7 7 8 8      10
    //         right  left
    if right >= 0 && nums[right] == target{
        res[1] = right
    }

    return res
}

27. Remove Element

👉 LeetCode

// 方法一
func removeElement(nums []int, val int) int {
    left, right := 0, len(nums) - 1
    for left <= right{
        if nums[left] == val {
            if nums[right] != val{
                nums[left], nums[right] = nums[right], nums[left]
                left++
                right--
            }else{
                right--
            }
        }else{
             if nums[right] != val{
               left ++
            }else{
                right--
                left ++
            }
        }
    }

    return right+1
}

// 方法二
// 快慢指针
// 新数组比旧数组短,从左填充
// String部分的Replace Space,新数组比旧数组长,从右填充
func removeElement(nums []int, val int) int {
    left := 0
    for _, v := range nums{
        if v != val{
            nums[left] = v
            left++
        }
    }

    return left
}

977. Squares of a Sorted Array

👉 LeetCode

// 方法一
func sortedSquares(nums []int) []int {
    res := make([]int, len(nums))
    left, right, k := 0, len(nums)-1, len(nums)-1
	for ; left <= right; k-- {
        if nums[left] * nums[left] > nums[right] * nums[right]{
            res[k] = nums[left] * nums[left]
            left++
        }else{
            res[k] = nums[right] * nums[right]
            right--
        }
    }
    return res
}

// 方法二
func sortedSquares(nums []int) []int {
    for i, value := range nums {
        nums[i] = value * value
    }
    sort.Ints(nums)
    return nums
}

209. Minimum Size Subarray Sum

👉 LeetCode

func minSubArrayLen(target int, nums []int) int {
    left, sum, res := 0, 0, len(nums) + 1
    for right, v := range nums{
        sum += v
        for sum >= target{
            res =  min(res, right - left + 1)
            sum -= nums[left]
            left ++
        }
    }

    if res == len(nums) + 1{
        res = 0
    }

    return res
}

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

59. Spiral Matrix II

👉 LeetCode

func generateMatrix(n int) [][]int {
    top, bottom := 0, n-1
    left, right := 0, n-1
    num := 1
    tar := n * n
    matrix := make([][]int, n)
    for i := 0; i < n; i++ {
        matrix[i] = make([]int, n)
    }
    for num <= tar {
        for i := left; i <= right; i++ {
            matrix[top][i] = num
            num++
        }
        top++
        for i := top; i <= bottom; i++ {
            matrix[i][right] = num
            num++
        }
        right--
        for i := right; i >= left; i-- {
            matrix[bottom][i] = num
            num++
        }
        bottom--
        for i := bottom; i >= top; i-- {
            matrix[i][left] = num
            num++
        }
        left++
    }
    return matrix
}

3. Longest Substring Without Repeating Characters

👉 LeetCode

func lengthOfLongestSubstring(s string) int {
    m := make(map[rune]int)
    left, res := 0, 0
    for right, v := range s{
        if v2, ok := m[v]; ok && left <= v2{
            left = v2 + 1
        }

        m[v] = right

        if v3 := right - left + 1; v3 > res{
            res = v3
        }
    }
    return res
}

35. Search Insert Position

👉 LeetCode

// 方法一
func searchInsert(nums []int, target int) int {
    left := 0
    right := len(nums)-1
    for left <= right {
        mid := left + (right - left) / 2 // 防求和溢出
        if nums[mid] == target {
            return mid
        }else if nums[mid] > target{
            right = mid - 1
        }else{
            left = mid + 1
        }
    }

	 // 此时 right + 1 == left
    // nums[right] < target < nums[left]

    return left
}

// 方法二
// nums[right] is the biggest number less than the target
func searchInsert(nums []int, target int) int {
    left, right := 0, len(nums)-1
    for left <= right {
        mid := left + (right-left)>>1
        if nums[mid] >= target {
            right = mid - 1
        } else {
            left = mid + 1
        }
    }
    return right+1
}

283. Move Zeroes

👉 LeetCode

func moveZeroes(nums []int)  {
    if len(nums) == 0{
        return
    }

    left := 0
    for right, v := range nums{
        if v != 0{
            nums[right] = 0
            nums[left] = v
            left++
        }
    }
}

func moveZeroes(nums []int) {
	// j stay on the index of zero
    j := 0
    for i := 0; i < len(nums); i++ {
        if nums[i] != 0 {
            if i != j {
                nums[i], nums[j] = nums[j], nums[i]
                j++
            } else {
                j++
            }
        }
    }
}

881. Boats to Save People

👉 LeetCode

import (
	"sort"
)

func numRescueBoats(people []int, limit int) int {
    sort.Ints(people)
    left, right, res := 0, len(people)-1, 0
    for left <= right {
        if left == right {
            res++
            return res
        }
        if people[left]+people[right] <= limit {
            left++
            right--
        } else {
            right--
        }
        res++
    }
    return res
}

304. Range Sum Query 2D - Immutable

👉 LeetCode

type NumMatrix struct {
    preSum [][]int
}

func Constructor(matrix [][]int) NumMatrix {
    m := len(matrix)
    n := len(matrix[0])

    preSum := make([][]int, m+1)
    for i := 0; i < m+1; i++{
        preSum[i] = make([]int, n+1)
    }

    for i := 0; i < m; i++{
        for j := 0; j < n; j++{
            // matrix[i][j] = preSum[i+1][j+1] - (preSum[i][j+1] - preSum[i+1][j] + preSum[i][j])
            preSum[i+1][j+1] = preSum[i][j+1] + preSum[i+1][j] - preSum[i][j] + matrix[i][j]
        }
    }
    return NumMatrix{preSum:preSum}

}

func (this *NumMatrix) SumRegion(row1 int, col1 int, row2 int, col2 int) int {
    preSum := this.preSum
    return preSum[row2+1][col2+1] - preSum[row2+1][col1] - preSum[row1][col2+1] + preSum[row1][col1]
}

Linked List

删反交换交点环

203. Remove Linked List Elements

👉 LeetCode

func removeElements(head *ListNode, val int) *ListNode {
    preHead := new(ListNode)
    preHead.Next = head
    pre := preHead
    cur := head
    for cur != nil{
        if cur.Val == val{
            pre.Next = cur.Next
            cur = cur.Next
        }else{
            pre = cur
            cur = cur.Next
        }
    }
    return preHead.Next
}

19. Remove Nth Node From End of List

👉 LeetCode

// cur.Next=nil, 倒数第1个节点
// cur.Next.Next=nil, 倒数第2个节点
// 按规律找出倒数第n+1个节点
func removeNthFromEnd(head *ListNode, n int) *ListNode {
	preHead := new(ListNode)
	preHead.Next = head
	left := preHead
	right := preHead
	for i := 0; i < n+1; i++{
		right = right.Next
	}
	for right != nil{
		right = right.Next
		left = left.Next
	}
	left.Next = left.Next.Next
	return preHead.Next
}

206. Reverse Linked List

👉 LeetCode

func reverseList(head *ListNode) *ListNode {
    var pre *ListNode
    cur := head
    for cur != nil{
        cur.Next, pre, cur = pre, cur, cur.Next
    }
    return pre
}

24. Swap Nodes in Pairs

👉 LeetCode

// 递归
func swapPairs(head *ListNode) *ListNode {
    if head == nil || head.Next == nil{
        return head
    }

    newHead := head.Next
    head.Next.Next, head.Next =  head, swapPairs(head.Next.Next)

    return newHead
}

// 迭代
func swapPairs(head *ListNode) *ListNode {
    preHead := new(ListNode)
    preHead.Next = head
    cur := preHead
    for cur.Next != nil && cur.Next.Next != nil{
        cur.Next,
        cur.Next.Next.Next,
        cur.Next.Next,
        cur =
        cur.Next.Next,
        cur.Next,
        cur.Next.Next.Next,
        cur.Next

        // cur, cur.Next, cur.Next.Next, cur.Next.Next.Next =
        // cur.Next, cur.Next.Next, cur.Next.Next.Next, cur.Next
    }
    return preHead.Next
}

Intersection of Two Linked Lists LCCI

👉 LeetCode

func getIntersectionNode(headA, headB *ListNode) *ListNode {
    curA, curB := headA, headB
    lengtA, lengtB := 0, 0
    for curA != nil{
        lengtA++
        curA = curA.Next
    }
    for curB != nil{
        lengtB++
        curB = curB.Next
    }
    curA, curB = headA, headB
    if lengtA < lengtB{
        lengtA, lengtB = lengtB, lengtA
        curA, curB = curB, curA
    }

    for i := 0; i < lengtA-lengtB; i++{
        curA = curA.Next
    }

    for i := 0; i < lengtB; i++{
        if curA == curB{
            return curA
        }
        curA = curA.Next
        curB = curB.Next
    }

    return nil
}

142. Linked List Cycle II

👉 LeetCode

fast: $ t = (x_{1} + x_{2} + x_{3} + x_{2}) \div 2 $

slow: $ t = (x_{1} + x_{2}) \div 1 $

$ x_{1} + x_{2} + x_{3} + x_{2} = (x_{1} + x_{2}) \times 2 \Longrightarrow x_{1} = x_{3} $

func detectCycle(head *ListNode) *ListNode {
    if head == nil|| head.Next == nil{
        return nil
    }

    intersection := findIntersection(head)
    // no circle
    if intersection == nil{
        return nil
    }

    fast := head
    slow := intersection
    for fast != slow {
        fast = fast.Next
        slow = slow.Next
    }
    return slow
}

func findIntersection(head *ListNode) *ListNode{
    fast, slow := head, head
    for slow != nil && fast != nil && fast.Next != nil{
        fast = fast.Next.Next
        slow = slow.Next
        if slow == fast{
            return slow
        }
    }
    return nil
}

Hash Table

242. Valid Anagram

👉 LeetCode

func isAnagram(s string, t string) bool {
    m := make(map[rune]int)
    for _, v := range s{
        m[v] ++
    }

    for _, v := range t{
        m[v] --
    }

    for _, v := range m{
        if v != 0{
            return false
        }
    }
    return true
}

383. Ransom Note

👉 LeetCode

func canConstruct(ransomNote string, magazine string) bool {
    m := make(map[rune]int)
    for _, v := range ransomNote{
        m[v]++
    }

    for _, v := range magazine{
        if _, ok := m[v]; ok{
            m[v]--
        }
    }

    for _, v := range m{
        if v > 0{
            return false
        }
    }

    return true
}

349. Intersection of Two Arrays

👉 LeetCode

func intersection(nums1 []int, nums2 []int) []int {
    m := make(map[int]bool)
    var res []int
    for _, n := range nums1 {
        m[n] = true
    }
    for _, n := range nums2 {
            if m[n] {
                //delete(m, n)
                m[n] = false
                res = append(res, n)
            }
    }
    return res
}

202. Happy Number

👉 LeetCode

func isHappy(n int) bool {
    m := make(map[int]bool)
    for n != 1{
        if m[n]{
            return false
        }
        m[n] = true
        n = calcu(n)
    }
    return true
}

func calcu(n int)int{
    sum := 0
    for n != 0{
        rem := n % 10
        sum = sum + rem*rem
        n = n / 10
    }
    return sum
}

1. Two Sum

👉 LeetCode

func twoSum(nums []int, target int) []int {
    m := make(map[int]int)
    for k, v := range nums{
        if v2, ok := m[target-v]; ok{
            return []int{v2, k}
        }else{
            m[v] = k
        }
    }
    return nil
}

15. 3Sum

👉 LeetCode

import "sort"

func threeSum(nums []int) [][]int {
    res := make([][]int, 0)
    sort.Ints(nums)
    length := len(nums)
    for i := 0; i < length; i++{
        // De-duplication
        // same with last element
        if i > 0 && nums[i] == nums[i-1]{
            continue
        }
        left, right := i+1, length-1
        for left < right{
            sum := nums[i] + nums[left] + nums[right]
            if sum < 0{
                left++
            }else if sum > 0{
                right--
            }else{
                res = append(res, []int{nums[i], nums[left], nums[right]})
                for left < right && nums[right] == nums[right-1]{
                    right--
                }
                for left < right && nums[left] == nums[left+1]{
                    left++
                }
                right--
                left++
            }
        }
    }
    return res
}


func threeSum(nums []int) [][]int {
    res := make([][]int, 0)
    sort.Ints(nums)
    for i := 0; i < len(nums); i++{
        if i > 0 && nums[i] == nums[i-1]{
            continue
        }

        left, right := i+1, len(nums)-1
        CHECK:
        for left < right{
            for left > i+1 && nums[left] == nums[left-1]{
                left++
                continue CHECK
            }

            for right < len(nums) - 1 && nums[right] == nums[right+1]{
                right--
                continue CHECK
            }

            if nums[i] + nums[left] + nums[right] == 0{
                res = append(res, []int{nums[i], nums[left], nums[right]})
                left++
                right--
            }else if nums[i] + nums[left] + nums[right] < 0{
                left++
            }else{
                right--
            }
        }
    }

    return res
}

18. 4Sum

👉 LeetCode

import "sort"

func fourSum(nums []int, target int) [][]int {
    sort.Ints(nums)
    length := len(nums)
    res := [][]int{}
    for i := 0; i < length; i++{
        if i > 0 && nums[i] == nums[i-1]{
            continue
        }

        for j := i+1; j < length; j++{
            if j > i+1 && nums[j] == nums[j-1]{
                continue
            }

            left, right := j+1, length-1
            CHECK:
            for left < right{
                for left > j+1 && nums[left] == nums[left-1]{
                    left++
                    continue CHECK
                }
                for right < length-1 && nums[right] == nums[right+1]{
                    right--
                    continue CHECK
                }
                sum := nums[i] + nums[j] + nums[left] + nums[right]
                if sum > target{
                    right--
                }else if sum < target{
                    left++
                }else{
                    res = append(res, []int{nums[i], nums[j], nums[left], nums[right]})
                    left++
                    right--
                }

            }
        }
    }
    return res
}

454. 4Sum II

👉 LeetCode

func fourSumCount(nums1 []int, nums2 []int, nums3 []int, nums4 []int) int {
    m := make(map[int]int, len(nums1)*len(nums2))
    for _, v := range nums1{
        for _, v2 := range nums2{
            m[v+v2] ++
        }
    }

    res := 0
    for _, v3 := range nums3{
        for _, v4 := range nums4{
            res += m[0-v3-v4]
        }
    }
    return res
}

String

344. Reverse String

👉 LeetCode

func reverseString(s []byte)  {
    left, right := 0, len(s)-1
    for left < right{
        s[left], s[right] = s[right], s[left]
        left++
        right--
    }
}

541. Reverse String II

👉 LeetCode

func reverseStr(s string, k int) string {
    b := []byte(s)
    length := len(b)
    for i := 0; i < length; i += 2*k{
        end := i+k
        if end > length{
            end = length
        }
        reverse(b[i:end])
    }
    return string(b)

}

func reverse(s []byte) {
    left, right := 0, len(s)-1
    for left < right{
        s[left], s[right] =  s[right], s[left]
        left++
        right--
    }
}

Replace Space

👉 LeetCode

func replaceSpace(s string) string {
    count := 0
    for _, v := range s{
        if v == ' '{
            count++
        }
    }
    b := make([]byte, len(s)+2*count)
    right := 0
    for _, v := range s{
        if v == ' '{
            b[right] = '%'
            b[right+1] = '2'
            b[right+2] = '0'
            right += 3
            continue
        }
        b[right] = byte(v)
        right++
    }
    return string(b)
}

func replaceSpace(s string) string {
    b := []byte(s)
    left := len(b)-1
    count := 0
    for i := 0; i <= left; i++{
        if b[i] == byte(' '){
            count++
        }
    }
    padding := make([]byte, 2*count)
    b = append(b, padding...)
    right := len(b)-1
    for left < right{
        if b[left] == byte(' '){
            b[right] = '0'
            b[right-1] = '2'
            b[right-2] = '%'
            right -= 3
            left--
            continue
        }
        b[right] = b[left]
        right--
        left--
    }
    return string(b)
}

151. Reverse Words in a String

👉 LeetCode

// method 1
func reverseWords(s string) string {
    ss := strings.Fields(s)
	reverse(ss)
	return strings.Join(ss, " ")
}

func reverse(m []string) {
    i := 0
    j := len(m)-1
    for i < j {
        m[i], m[j] = m[j], m[i]
        i++
        j--
    }
}

// method 2
func reverseWords(s string) string {
    b := []byte(s)
    b = removeExtraSpaces(b)
    reverse(b)
    wordstart := 0
    for k, v := range b{
        if  k == len(b)-1{
            reverse(b[wordstart:])
        }
        if v == ' ' {
            reverse(b[wordstart: k])
            wordstart = k + 1
        }
    }
    return string(b)
}

func removeExtraSpaces(b []byte) []byte{
    fast := 0
    for fast < len(b) && b[fast] == ' '{
        fast++
    }

    slow := 0
    for ; fast < len(b); fast++{
        cond1 := b[fast] != ' '
        cond2 := b[fast] == ' ' && fast > 0 && b[fast-1] != ' '
        if cond1 || cond2{
            b[slow] = b[fast]
            slow++
        }
    }

    if b[slow-1] == ' '{
        return b[:slow-1]
    }else{
        return b[:slow]
    }
}

28. Implement strStr()

👉 LeetCode

// 方法一:KMP

// H: AABAACAABAACAABAAD
// N: AABAACAABAAD
// i是haystack下标,j是needle的下标

// H[0:11] == N[0:11], 前11次比较匹配
// 第12次比较不匹配,即i = j = 11时,H[11] != N[11]

// 由 j = next[j-1] = next(11-1) = 5,表示前5次比较是匹配的
// 也就是 H[6:11] == N[0:5]

// 因此可以直接从H[11] 与 N[5]开始比较,H的遍历过程没有回退
// 复杂度O(n)

func strStr(haystack string, needle string) int {
    next := getNext(needle)
    j := 0
    for i := 0; i < len(haystack); i++ {
        for j > 0 && haystack[i] != needle[j] {
            j = next[j-1]
        }

        if haystack[i] == needle[j] {
            j++
        }

        if j == len(needle) {
            return i - j + 1
        }
    }
    return -1
}

// needle:  a d c a d d e
// next:    0 0 0 1 2 0 0

// needle:  a a b a a f
// next:    0 1 0 1 2 0
func getNext(needle string) []int {
    next := make([]int, len(needle))
    next[0] = 0
    for right := 1; right < len(needle); right++ {
        //
        left := next[right-1]
        for left > 0 && needle[right] != needle[left] {
            left = next[left-1]
        }

        if needle[right] == needle[left] {
            left++
        }

        next[right] = left
    }
    return next
}

// 方法二
func strStr(haystack string, needle string) int {
    if needle == ""{
        return 0
    }
    for i, j := 0, len(needle); j <= len(haystack); i, j = i+1, j+1{
        if haystack[i:j] == needle{
            return i
        }
    }
    return -1
}

459. Repeated Substring Pattern

👉 LeetCode

func repeatedSubstringPattern(s string) bool {
    for i := 1; i < len(s)/2 + 1; i++{
        if len(s) % i != 0{
            continue
        }
        for j := 1; j < len(s)/i; j++{
            if s[0:i] != s[j*i:j*i+i]{
                break
            }
            // 成功匹配最后一段
            if j == len(s)/i -1 {
                return true
            }
        }
    }
    return false
}

//KMP
func repeatedSubstringPattern(s string) bool {
    if len(s) < 2{
        return false
    }
    next := getNext(s)
    a := next[len(s)-1]  // 最长相同前后缀的长度
    b := len(s) - a // 重复子串长度

    if a > 0 && len(s) % b  == 0{
        return true
    }
    return false
}

func getNext(needle string) []int {
	next := make([]int, len(needle))
	next[0] = 0
	for right := 1; right < len(needle); right++ {
		left := next[right-1]
		for left > 0 && needle[right] != needle[left] {
			left = next[left-1]
		}
		if needle[right] == needle[left] {
			left++
		}
		next[right] = left
	}
	return next
}

Stack and Queue

20. Valid Parentheses

👉 LeetCode

func isValid(s string) bool {
    stack := make([]rune, 0)
    for _, v := range s{
        switch v{
            case '(':
                stack = append(stack, ')')
            case '[':
                stack = append(stack, ']')
            case '{':
                stack = append(stack, '}')
            default:
                if len(stack) > 0 && stack[len(stack)-1] == v{
                    stack = stack[:len(stack)-1] // 出栈
                }else{
                    return false
                }
        }
    }
    return len(stack) == 0
}

1047. Remove All Adjacent Duplicates In String

👉 LeetCode

func removeDuplicates(s string) string {
    stack := make([]rune, 0)
    for _, v := range s{
        if len(stack) > 0 && stack[len(stack)-1] == v{
            stack = stack[:len(stack)-1]
        }else{
            stack = append(stack, v)
        }
    }
    return string(stack)
}

150. Evaluate Reverse Polish Notation

👉 LeetCode

func evalRPN(tokens []string) int {
    var stack []int
    for _, v := range tokens{
        switch v{
            case "+":
                stack[len(stack)-2] = stack[len(stack)-2] + stack[len(stack)-1]
                stack = stack[:len(stack)-1]
            case "-":
                stack[len(stack)-2] = stack[len(stack)-2] - stack[len(stack)-1]
                stack = stack[:len(stack)-1]
            case "*":
                stack[len(stack)-2] = stack[len(stack)-2] * stack[len(stack)-1]
                stack = stack[:len(stack)-1]
            case "/":
                stack[len(stack)-2] = stack[len(stack)-2] / stack[len(stack)-1]
                stack = stack[:len(stack)-1]
            default:
                v2, _ := strconv.Atoi(v)
                stack = append(stack, v2)
        }
    }
    return stack[0]
}

239. Sliding Window Maximum

👉 LeetCode

func maxSlidingWindow(nums []int, k int) []int {
    queue := make([]int, 0)
    res := make([]int, 0)
    for i, v := range nums{
        // 处理离开窗口的元素
        if i >= k && nums[i-k] == queue[0]{
            queue = queue[1:]
        }

        // 处理进入窗口的元素
        for len(queue) > 0 && v > queue[len(queue)-1]{
            queue = queue[0:len(queue)-1]
        }
        queue = append(queue, v)

        // 记录窗口最大值
        if i >= k-1 {
            res = append(res, queue[0])
        }
    }
    return res
}

347. Top K Frequent Elements

👉 LeetCode

import "sort"

func topKFrequent(nums []int, k int) []int {
    m := make(map[int]int)
    for _, num := range nums{
        m[num]++
    }

    keys := []int{}
    for key, _ := range m{
        keys = append(keys, key)
    }

    sort.Slice(keys, func(i, j int)bool{
        return m[keys[i]] >  m[keys[j]]
    })

    return keys[:k]
}

Binary Tree

94. 144. 145. Binary Tree Traversal

👉 LeetCode Preorder
👉 LeetCode Inorder
👉 LeetCode Postorder

//type TreeNode struct {
 //    Val int
 //    Left *TreeNode
 //    Right *TreeNode
 //}

// 递归法
func preorderTraversal(root *TreeNode) []int {
    res := []int{}
    var rec func(*TreeNode)
    rec = func(node *TreeNode){
        if node == nil{
            return
        }
        res = append(res, node.Val)
        rec(node.Left)
        rec(node.Right)
    }
    rec(root)
    return res
}

func inorderTraversal(root *TreeNode) []int {
    res := []int{}
    var rec func(*TreeNode)
    rec = func(node *TreeNode){
        if node == nil{
            return
        }
        rec(node.Left)
        res = append(res, node.Val)
        rec(node.Right)
    }
    rec(root)
    return res
}

func postorderTraversal(root *TreeNode) []int {
    res := []int{}
    var rec func(*TreeNode)
    rec = func(node *TreeNode){
        if node == nil{
            return
        }
        rec(node.Left)
        rec(node.Right)
        res = append(res, node.Val)
    }
    rec(root)
    return res
}

// 迭代法
func preorderTraversal(root *TreeNode) []int {
    res := make([]int, 0)
    stack := make([]*TreeNode, 0)
    if root != nil{
        stack = append(stack, root)
    }
    for len(stack) > 0 {
        // 出栈
        node := stack[len(stack)-1]
        stack = stack[:len(stack)-1]
        if node != nil{
            // 右入栈
            if node.Right != nil{
                stack = append(stack, node.Right)
            }
            // 左入栈
            if node.Left != nil{
                stack = append(stack, node.Left)
            }
            // 中入栈
            // 再次入栈时后面加一个读标记
            stack = append(stack, node, nil)
        }else{
            // 读取数据
            res = append(res, stack[len(stack)-1].Val)
            stack = stack[:len(stack)-1]
        }
    }
    return res
}

func inorderTraversal(root *TreeNode) []int {
    res := make([]int, 0)
    stack := make([]*TreeNode, 0)
    if root != nil{
        stack = append(stack, root)
    }
    for len(stack) > 0 {
        // 出栈
        node := stack[len(stack)-1]
        stack = stack[:len(stack)-1]
        if node != nil{
            // 右入栈
            if node.Right != nil{
                stack = append(stack, node.Right)
            }

            // 中入栈
            // 再次入栈时后面加一个读标记
            stack = append(stack, node, nil)

            // 左入栈
            if node.Left != nil{
                stack = append(stack, node.Left)
            }
        }else{
            res = append(res, stack[len(stack)-1].Val)
            stack = stack[:len(stack)-1]
        }
    }
    return res
}

func inorderTraversal(root *TreeNode) []int {
    res := make([]int, 0)
    stack := make([]*TreeNode, 0)
    node := root
    for node != nil || len(stack) > 0 {
        for node != nil{
            stack = append(stack, node)
            node = node.Left
        }

        node = stack[len(stack)-1]
        stack = stack[:len(stack)-1]

        res = append(res, node.Val)

        node = node.Right
    }
    return res
}

func postorderTraversal(root *TreeNode) []int {
    res := make([]int, 0)
    stack := make([]*TreeNode, 0)
    if root != nil{
        stack = append(stack, root)
    }
    for len(stack) > 0 {
        // 出栈
        node := stack[len(stack)-1]
        stack = stack[:len(stack)-1]
        if node != nil{
            // 再次入栈时后面加一个标记
            stack = append(stack, node, nil)

            if node.Right != nil{
                stack = append(stack, node.Right)
            }

            if node.Left != nil{
                stack = append(stack, node.Left)
            }
        }else{
            res = append(res, stack[len(stack)-1].Val)
            stack = stack[:len(stack)-1]
        }
    }
    return res
}

102. Binary Tree Level Order Traversal

👉 LeetCode

func levelOrder(root *TreeNode) [][]int {
    queue := make([]*TreeNode, 0)
    if root != nil{
        queue = append(queue, root)
    }

    res := make([][]int, 0)

    for len(queue) > 0{
        row := make([]int, 0)

        // 每层节点的数量
        n := len(queue)

        // 同层的节点都出队列
        // 出队列的同时把下一层的节点加入队列
        for i := 0; i < n; i++{
            node := queue[0]
            queue = queue[1:]

            row = append(row, node.Val)

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

    return res
}

107. Binary Tree Level Order Traversal II

👉 LeetCode

func levelOrderBottom(root *TreeNode) [][]int {
    queue := make([]*TreeNode, 0)
    if root != nil{
        queue = append(queue, root)
    }

    res := make([][]int, 0)

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

104. Maximum Depth of Binary Tree

👉 LeetCode

// 递归,分解问题
func maxDepth(root *TreeNode) int {
    if root == nil{
        return 0
    }

    maxLeft := maxDepth(root.Left)
    maxRight := maxDepth(root.Right)

    if maxLeft > maxRight{
        return maxLeft + 1
    }

    return maxRight + 1
}

// 递归,遍历二叉树
func maxDepth(root *TreeNode) int {
    res, deepth := 0, 0
    var rec func(*TreeNode)
    rec = func(root *TreeNode){
        if root == nil{
            if deepth > res{
                res = deepth
            }
            return
        }

        deepth++
        rec(root.Left)
        // deepth--

        // deepth++
        rec(root.Right)
        deepth--
    }

    rec(root)
    return res
}

// 迭代法, 遍历二叉树
func maxDepth(root *TreeNode) int {
    queue := make([]*TreeNode, 0)
    if root != nil{
        queue = append(queue, root)
    }

    res := 0

    for len(queue) > 0{
        res++

        // 每层节点的数量
        n := len(queue)

        // 同层的节点都出队列
        // 出队列的同时把下一层的节点加入队列
        for i := 0; i < n; i++{
            node := queue[0]
            queue = queue[1:]

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

    return res
}

111. Minimum Depth of Binary Tree

👉 LeetCode

func minDepth(root *TreeNode) int {
    queue := make([]*TreeNode, 0)
    if root != nil{
        queue = append(queue, root)
    }

    res := 0

    for len(queue) > 0{
        res++

        // 每层节点的数量
        n := len(queue)

        // 同层的节点都出队列
        // 出队列的同时把下一层的节点加入队列
        for i := 0; i < n; i++{
            node := queue[0]
            queue = queue[1:]

            if node.Left == nil && node.Right == nil{
                return res
            }

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

    return res
}

226. Invert Binary Tree

👉 LeetCode

把每一个节点的左右孩子交换一下

// 分解问题
func invertTree(root *TreeNode) *TreeNode {
    if root == nil{
        return nil
    }

    l := invertTree(root.Left)
    r := invertTree(root.Right)
    root.Left, root.Right = r, l

    return root
}

// 递归遍历
func invertTree(root *TreeNode) *TreeNode {
    var rec func(*TreeNode)
    rec = func(node *TreeNode){
        if node == nil{
            return
        }
        rec(node.Left)
        rec(node.Right)
        node.Left, node.Right = node.Right, node.Left
    }

    rec(root)
    return root
}

// 迭代遍历
func invertTree(root *TreeNode) *TreeNode {
    queue := make([]*TreeNode, 0)
    if root != nil{
        queue = append(queue, root)
    }

    for len(queue) > 0{
        node := queue[0]
        queue = queue[1:]
        if node.Left != nil{
            queue = append(queue, node.Left)
        }
        if node.Right != nil{
            queue = append(queue, node.Right)
        }
        node.Left, node.Right = node.Right, node.Left
    }
    return root
}

101. Symmetric Tree

👉 LeetCode

// 递归
func isSymmetric(root *TreeNode) bool {
    var rec func(left, right *TreeNode)bool
    rec = func(left, right *TreeNode)bool{
        if left == nil && right == nil{
            return true
        }else if left == nil && right != nil{
            return false
        }else if left != nil && right == nil{
            return false
        }else if left != nil && right != nil && left.Val != right.Val{
            return false
        }

        // 匹配外侧,匹配内侧
        if rec(left.Left, right.Right) && rec(left.Right, right.Left){
            return true
        }

        return false
    }

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

// 迭代
func isSymmetric(root *TreeNode) bool {
    queue := make([]*TreeNode, 0)
    if root != nil{
        queue = append(queue, root.Left, root.Right)
    }

    for len(queue) > 0{
        l, r := queue[0], queue[1]
        queue = queue[2:]
        if l == nil && r == nil{
            continue
        }else if l == nil && r != nil || l != nil && r == nil ||
            l != nil && r != nil && l.Val != r.Val{
            return false
        }

        queue = append(queue, l.Left)
        queue = append(queue, r.Right)
        queue = append(queue, l.Right)
        queue = append(queue, r.Left)
    }

    return true
}

110. Balanced Binary Tree

👉 LeetCode

func isBalanced(root *TreeNode) bool {
    var getDepth func(*TreeNode) int
    getDepth = func(node *TreeNode) int{
        if node == nil{
            return 0
        }

        ld, rd := getDepth(node.Left), getDepth(node.Right)

        // 不平衡时返回-1
        if ld < 0 || rd < 0 || ld - rd > 1 || rd - ld > 1{
            return -1
        }

        if ld > rd{
            return ld + 1
        }

        return rd + 1
    }

    return getDepth(root) > -1
}

257. Binary Tree Paths

👉 LeetCode

// dfs
func binaryTreePaths(root *TreeNode) []string {
    res := make([]string, 0)
    var rec func(*TreeNode, string)
    rec = func(node *TreeNode, path string){
        if node == nil{
            return
        }
        path += "->" + strconv.Itoa(node.Val)
        if node.Left == nil && node.Right == nil{
            res = append(res, path[2:])
            return
        }
        rec(node.Left, path)
        rec(node.Right, path)
    }
    rec(root, "")
    return res
}

// bfs
func binaryTreePaths(root *TreeNode) []string {
    res := make([]string, 0)
    queue := make([]*TreeNode, 0)
    paths := make([]string, 0)
    if root != nil{
        queue = append(queue, root)
        paths = append(paths, strconv.Itoa(root.Val))
    }

    for len(queue) > 0{
        node := queue[0]
        queue = queue[1:]
        path := paths[0]
        paths = paths[1:]

        if node != nil{
            // 叶节点完成一个path
            if node.Left == nil && node.Right == nil{
                res = append(res, path)
            }
            if node.Right != nil{
                queue = append(queue, node.Right)
                paths = append(paths, path + "->" + strconv.Itoa(node.Right.Val))
            }
            if node.Left != nil{
                queue = append(queue, node.Left)
                paths = append(paths, path + "->" + strconv.Itoa(node.Left.Val))
            }
        }
    }

    return res
}

404. Sum of Left Leave

👉 LeetCode

func sumOfLeftLeaves(root *TreeNode) int {
    sum := 0
    var rec func(*TreeNode)
    rec = func(root *TreeNode){
        if root == nil{
            return
        }
        if root != nil && root.Left != nil &&
            root.Left.Left == nil && root.Left.Right == nil{
            sum += root.Left.Val
        }
        rec(root.Left)
        rec(root.Right)
    }

    rec(root)

    return sum
}

func sumOfLeftLeaves(root *TreeNode) int {
    res := 0
    queue := make([]*TreeNode, 0)
    if root != nil{
        queue = append(queue, root)
    }

    for len(queue) > 0{
        node := queue[0]
        queue = queue[1:]

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

            if node.Left != nil{
                // 是左节点
                if node.Left.Left == nil && node.Left.Right == nil{
                    res += node.Left.Val
                }else{
                    queue = append(queue, node.Left)
                }
            }
        }
    }

    return res
}

113. Path Sum II

👉 LeetCode

func pathSum(root *TreeNode, targetSum int) [][]int {
    res := make([][]int, 0)
    var rec func(*TreeNode, []int, int)
    rec = func(node *TreeNode, path []int, sum int){
        if node == nil{
            return
        }

        path = append(path, node.Val)
        sum -= node.Val

        if node.Left == nil && node.Right == nil && sum == 0{
            res = append(res,append([]int{}, path...)) // 这里需要拷贝
        }

        rec(node.Left, path, sum)
        rec(node.Right, path, sum)
    }

    rec(root, []int(nil), targetSum)

    return res
}

106. Construct Binary Tree from Inorder and Postorder Traversal

👉 LeetCode

func buildTree(inorder []int, postorder []int) *TreeNode {
    if len(inorder) == 0{
            return nil
    }

    node := new(TreeNode)
    // 根节点为后序数组的最后一个元素
    node.Val = postorder[len(postorder)-1]

    // 求左右子树的分割线
    index := 0
    for k, v := range inorder{
        if v == node.Val{
            index = k
            break
        }
    }
    // 求左右子树的中序数组
    lin, rin := inorder[:index], inorder[index+1:]
    // 求左右子树的后序数组
    lpost, rpost := postorder[:len(lin)], postorder[len(lin):len(rin)+len(lin)]

    node.Left = buildTree(lin, lpost)
    node.Right = buildTree(rin, rpost)

    return node
}

617. Merge Two Binary Trees

👉 LeetCode

func mergeTrees(root1 *TreeNode, root2 *TreeNode) *TreeNode {
    if root1 == nil {
        return root2
    }
    if root2 == nil {
        return root1
    }

    root := new(TreeNode)
    root.Val = root1.Val + root2.Val
    root.Left = mergeTrees(root1.Left, root2.Left)
    root.Right = mergeTrees(root1.Right, root2.Right)

    return root
}

700. Search in a Binary Search Tree

👉 LeetCode

func searchBST(root *TreeNode, val int) *TreeNode {
    for root != nil{
        if val > root.Val{
            root = root.Right
        }else if val < root.Val{
            root = root.Left
        }else{
            break
        }
    }
    return root
}

501. Find Mode in Binary Search Tree

👉 LeetCode

// 中序遍历, 递归、迭代
// 与前一个节点值比较
// pre, node0, node1, node2, ...
func findMode(root *TreeNode) []int {
    res, count, max :=  make([]int, 0), 1, 1
    var pre *TreeNode
    var rec func(*TreeNode)
    rec = func(cur *TreeNode){
        if cur == nil{
            return
        }

        // 遍历左
        rec(cur.Left)

        // 对访问节点的处理
        if pre != nil && cur.Val == pre.Val{
            count++
        }else{
            count = 1
        }

        if count == max{
            res = append(res, cur.Val)
        }else if count > max{
            max = count
            res = []int{cur.Val}
        }

        pre = cur

        // 遍历右
        rec(cur.Right)
    }

    rec(root)

    return res
}

235. Lowest Common Ancestor of a Binary Search Tree

👉 LeetCode

// 递归
func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
    if root == nil {
        return nil
    }

    // p, q在左子树
    if p.Val < root.Val && q.Val < root.Val{
        return lowestCommonAncestor(root.Left, p, q)
    }

    // p, q在右子树
    if p.Val > root.Val && q.Val > root.Val{
        return lowestCommonAncestor(root.Right, p, q)
    }

    // p, q在两侧
    return root
}

// 迭代法
func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
    for root != nil{
        if p.Val < root.Val && q.Val < root.Val{
            root = root.Left
        }else if p.Val > root.Val && q.Val > root.Val{
            root = root.Right
        }else{
            return root
        }
    }

    return nil
}

701. Insert into a Binary Search Tree

👉 LeetCode

func insertIntoBST(root *TreeNode, val int) *TreeNode {
    if root == nil {
        return &TreeNode{Val: val}
    }

    if val > root.Val {
        root.Right = insertIntoBST(root.Right, val)
    } else {
        root.Left = insertIntoBST(root.Left, val)
    }

    return root
}

450. Delete Node in a BST

👉 LeetCode

func deleteNode(root *TreeNode, key int) *TreeNode {
    if root == nil{
        return nil
    }

    if root.Val == key{
        if root.Right == nil{
            return root.Left
        }

        // 求右子树最小值节点
        node := root.Right
        for node.Left != nil{
            node = node.Left
        }

        root.Val = node.Val
        root.Right = deleteNode(root.Right, node.Val)
        return root
    }

    root.Left = deleteNode(root.Left, key)
    root.Right = deleteNode(root.Right, key)
    return root
}

func deleteNode(root *TreeNode, key int) *TreeNode {
    if root == nil{
        return nil
    }

    if root.Val == key{
        node := root.Right
        if node == nil{
            return root.Left
        }

        // 求右子树最小值节点
        for node.Left != nil{
            node = node.Left
        }

        root.Val, node.Val = node.Val, root.Val
    }

    root.Left = deleteNode(root.Left, key)
    root.Right = deleteNode(root.Right, key)
    return root
}

669. Trim a Binary Search Tree

👉 LeetCode

// 递归
func trimBST(root *TreeNode, low int, high int) *TreeNode {
    if root == nil{
        return nil
    }

    if high < root.Val{
        return trimBST(root.Left, low, high)
    }

     if low > root.Val{
        return trimBST(root.Right, low, high)
    }

    root.Left = trimBST(root.Left, low, high)
    root.Right = trimBST(root.Right, low, high)

    return root
}

// 迭代
func trimBST(root *TreeNode, low int, high int) *TreeNode {
    if root == nil{
        return nil
    }

    for root != nil && (high < root.Val || low > root.Val) {
        if root.Val > high{
            root = root.Left
        }else {
            root = root.Right
        }
    }

    cur := root
    for cur != nil{
        // 不断增大左节点的值
        for cur.Left != nil && cur.Left.Val < low{
            cur.Left = cur.Left.Right
        }
        cur = cur.Left
    }

    cur = root
    for cur != nil{
        for cur.Right != nil && cur.Right.Val > high{
            cur.Right = cur.Right.Left
        }
        cur = cur.Right
    }

    return root
}

108. Convert Sorted Array to Binary Search Tree

👉 LeetCode

// 递归
func sortedArrayToBST(nums []int) *TreeNode {
    if len(nums) == 0{
        return nil
    }

    root := new(TreeNode)
    index := len(nums)/2
    root.Val = nums[index]
    root.Left = sortedArrayToBST(nums[:index])
    root.Right = sortedArrayToBST(nums[index+1:]) // 这里不会下标越界

    return root
}

// 迭代
// 中序遍历填充平衡树
func sortedArrayToBST(nums []int) *TreeNode {
    root := getTree(len(nums))
    stack := make([]*TreeNode, 0)
    stack = append(stack, root)

    k := 0

    for len(stack) > 0{
        node := stack[len(stack)-1]
        stack = stack[:len(stack)-1]
        if node != nil{
            if node.Right != nil {
                stack = append(stack, node.Right)
            }
            stack = append(stack, node, nil)
            if node.Left != nil {
                stack = append(stack, node.Left)
            }
        }else{
            stack[len(stack)-1].Val = nums[k]
            stack = stack[:len(stack)-1]
            k++
        }
    }
    return root
}

// 层级遍历构建平衡树
func getTree(num int)*TreeNode{
    root := new(TreeNode)
    queue := make([]*TreeNode, 0)
    queue = append(queue, root)
    count := 1

    for len(queue) > 0{
        n := len(queue)
        for i := 0; i < n; i++{
            node := queue[0]
            queue = queue[1:]

            if count < num{
                node.Left = new(TreeNode)
                queue = append(queue, node.Left)
                count++
            }
            if count < num{
                node.Right = new(TreeNode)
                queue = append(queue, node.Right)
                count++
            }
        }
    }

    return root
}

538. Convert BST to Greater Tree

👉 LeetCode

// 递归
func convertBST(root *TreeNode) *TreeNode {
    var sum int
    var rec func(*TreeNode)
    rec = func(node *TreeNode){
        if node == nil{
            return
        }
        rec(node.Right)
        sum += node.Val
        node.Val = sum
        rec(node.Left)
    }

    rec(root)
    return root
}

// 迭代
func convertBST(root *TreeNode) *TreeNode {
    stack := make([]*TreeNode, 0)
    if root != nil{
        stack = append(stack, root)
    }

    sum := 0

    for len(stack) > 0{
        node := stack[len(stack)-1]
        stack = stack[:len(stack)-1]
        if node != nil{
            if node.Left != nil {
                stack = append(stack, node.Left)
            }
            stack = append(stack, node, nil)
            if node.Right != nil {
                stack = append(stack, node.Right)
            }
        }else{
            node2 := stack[len(stack)-1]
            sum += node2.Val
            node2.Val = sum
            stack = stack[:len(stack)-1]
        }
    }
    return root
}

116. Populating Next Right Pointers in Each Node

👉 LeetCode

func connect(root *Node) *Node {
    if root == nil{
        return nil
    }

    var rec func(*Node, *Node)
    rec = func(l, r *Node){
        if l == nil || r == nil{
            return
        }
        l.Next = r
        rec(l.Left, l.Right)
        rec(r.Left, r.Right)
        rec(l.Right, r.Left)
    }

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

Sort

👉 LeetCode

Quick Sort

func sortArray(nums []int) []int {
    var quickSort func(*[]int, int, int)
    quickSort = func(nums *[]int, left, right int){
        if right - left + 1 < 2{
            return
        }
        p := part(nums, left, right)
        quickSort(nums, left, p-1)
        quickSort(nums, p+1, right)
    }

    quickSort(&nums, 0, len(nums)-1)

    return nums
}

func part(numsPtr *[]int, left, right int)int{
    nums := *numsPtr
    v := nums[left]
    for left < right{
        for left < right && nums[right] >= v{
            right--
        }
        nums[left] = nums[right]
        for left < right && nums[left] <= v{
            left++
        }
        nums[right] = nums[left]
    }
    nums[left] = v
    return left
}

// 快排
func sortArray(nums []int) []int {
    if len(nums) < 2{
        return nums
    }

    p := part(nums)
    sortArray(nums[:p])
    sortArray(nums[p+1:])

    return nums
}

func part(nums []int)int{
    if len(nums) < 2{
        return 0
    }
    v := nums[0]
    left, right := 0, len(nums) - 1
    for left < right{
        for left < right && nums[right] >= v{
            right--
        }
        nums[left] = nums[right]
        for left < right && nums[left] <= v{
            left++
        }
        nums[right] = nums[left]
    }
    nums[left] = v
    return left
}

Merge Sort

func sortArray(nums []int) []int {
    if len(nums) < 2{
        return nums
    }

    mid := len(nums) / 2
    nums1 := sortArray(nums[:mid])
    nums2 := sortArray(nums[mid:])
    nums = merge(nums1, nums2)

    return nums
}

func merge(nums1, nums2 []int)[]int{
    if len(nums1) == 0 {
        return nums2
    }else if len(nums2) == 0{
        return nums1
    }

    res := make([]int, 0, len(nums1)+len(nums2))
    i, j := 0, 0
    for i < len(nums1) && j < len(nums2){
        if nums1[i] < nums2[j]{
            res = append(res, nums1[i])
            i++
        }else{
            res = append(res, nums2[j])
            j++
        }
    }

    if i < len(nums1){
        res = append(res, nums1[i:]...)
    }else if j < len(nums2){
        res = append(res, nums2[j:]...)
    }

    return res
}

Bubble Sort

// swap len(array) - 1 time
// swap len(array) - 2 time
// ...
// swap 1 time

func BubbleSort(array []int) []int {
	for n := len(array) - 1; n >= 1; n-- {
		for i := 0; i < n; i++ {
			if array[i] > array[i+1] {
				array[i], array[i+1] = array[i+1], array[i]
			}
		}
	}
	return array
}

Selection Sort

// select min of array[0:] and store at 0th index
// select min of array[1:] and store at 1th index
// ...

func SelectionSort(array []int) []int {
	for i := 0; i < len(array)-1; i++ {
		idxOfMin := i
		for j := i; j < len(array); j++ {
			if array[j] < array[idxOfMin] {
				idxOfMin = j
			}
		}
		array[i], array[idxOfMin] = array[idxOfMin], array[i]
	}
	return array
}

Insertion Sort

// array[0:i] sorted
// array[i:] unsorted
// insert ith num into sorted array[:i]

func InsertionSort(array []int) []int {
	for i := 1; i < len(array); i++ {
		for j := i - 1; j >= 0; j-- {
			if array[j] > array[j+1] {
				array[j], array[j+1] = array[j+1], array[j]
				continue
			}
			break
		}

	}

	return array
}

215. Kth Largest Element in an Array

👉 LeetCode

func findKthLargest(nums []int, k int) int {

    index := part(nums)
    if index == len(nums) - k{
        return nums[index]
    }

    if index < len(nums) - k{
        return findKthLargest(nums[index+1:], k)
    }

    return findKthLargest(nums[:index], index - len(nums) + k)
}

func part(nums []int)int{
    if len(nums) == 0{
        return 0
    }
    left, right := 0, len(nums) - 1
    v := nums[0]
    for left < right{
        for left < right && nums[right] >= v{
            right--
        }
        nums[left] = nums[right]
        for left < right && nums[left] <= v{
            left++
        }
        nums[right] = nums[left]
    }

    nums[left] = v

    return left
}

Back Tracking

77. Combinations

👉 LeetCode

Input: n = 4, k = 2
Output:
[
[2,4],
[3,4],
[2,3],
[1,2],
[1,3],
[1,4],
]

func combine(n int, k int) [][]int {
    var res [][]int
    var rec func(int, []int)
    rec = func(start int, path []int){
        if len(path) == k{
            res = append(res, append(make([]int, 0, k), path...))
            return
        }

        // 还需要 k-len(path) 个元素
        // 最多还可以追加 n - i + 1 个元素
        // n - i + 1 >= k - len(path)
        // i <= n - k + len(path) + 1
        for i := start; i <= n- k + len(path) + 1; i++{
            path = append(path, i)
            rec(i+1, path)
            path = path[:len(path)-1]
        }
    }

    rec(1, make([]int, 0, k))
    return res
}

// 递归不传参数
func combine(n int, k int) [][]int {
    var res [][]int
    path := make([]int, 0, k)
    var rec func(int)
    rec = func(start int){
        if len(path) == k{
            res = append(res, append(make([]int, 0, k), path...))
            return
        }

        for i := start; i <= n - k + len(path) + 1; i++{
            path = append(path, i)
            rec(i+1)
            path = path[:len(path)-1]
        }
    }
    rec(1)
    return res
}

39. Combination Sum

👉 LeetCode

Input: candidates = [2,3,5], target = 8
Output: [[2,2,2,2],[2,3,3],[3,5]]

func combinationSum(candidates []int, target int) [][]int {
    var res [][]int
    var path []int
    var rec func(int)
    rec = func(start int){
        if target <= 0{
            if target == 0{
                res = append(res, append(make([]int, 0), path...))
            }
            return
        }

        for i := start; i < len(candidates); i++{
            path = append(path, candidates[i])
            target -= candidates[i]
            rec(i)
            path = path[:len(path)-1]
            target += candidates[i]
        }
    }
    rec(0)
    return res
}

93. Restore IP Addresses

👉 LeetCode

func restoreIpAddresses(str string) []string {
	res := make([]string, 0)
	var rec func(int, []string)
	rec = func(start int, parts []string){
		if len(parts) == 3{
			part := str[start:]
			if validIpPart(part){
				parts = append(parts, part)
				res = append(res, strings.Join(parts, "."))
			}
			return
		}

		for end := start+1; end <= start + 3 && end <= len(str); end++{
			part := str[start:end]
			if !validIpPart(part){
				continue
			}
			parts = append(parts, part)
			rec(end, parts)
			parts = parts[:len(parts)-1]
		}
	}

	rec(0, []string(nil))
	return res
}

func validIpPart(str string) bool{
	if len(str) == 0{
		return false
	}
    if str[0:1] == "0" && str != "0"{
		return false
	}
	if len(str) > 3{
		return false
	}
	if len(str) == 3 && str > "255"{
		return false
	}
	return true
}

// method 2
func restoreIpAddresses(s string) []string {
    var res []string
    k := 3 // 放入3个点
    n := len(s) - 1 // 可放点的位置数量
    var path []int
    var rec func(int)
    rec = func(start int){
        if len(path) == k{
            if ip, ok := isValidIP(s, path); ok{
                res = append(res, ip)
            }
            return
        }

        // n - i + 1 = k - len(path)
        for i := start; i <= n - k + len(path) + 1; i++{
            path = append(path, i)
            rec(i+1)
            path = path[:len(path)-1]
        }
    }
    rec(1)
    return res
}

func isValidIP(s string, path []int)(string, bool){
    segments := []string{
		str[:indice[0]],
		str[indice[0]:indice[1]],
		str[indice[1]:indice[2]],
		str[indice[2]:],
	}
    for _, v := range segments{
        if !isValidSeg(v){
            return "", false
        }
    }
    return strings.Join(segments, "."), true
}

func isValidSeg(s string)bool{
    if len(s) > 1 && s[0] == '0'{
        return false
    }
    if len(s) > 3{
        return false
    }
    if len(s) == 3 && s > "255"{
        return false
    }
    return true
}

90. Subsets II

👉 LeetCode

Input: nums = [1,2,2]
Output: [[],[1],[1,2],[1,2,2],[2],[2,2]]

func subsetsWithDup(nums []int) [][]int {
    sort.Ints(nums) // 去重关键
    var res [][]int
    var path []int
    var rec func(int)
    rec = func(start int){
        res = append(res, append(make([]int, 0), path...))
        for i := start; i < len(nums); i++{
            if i > start && nums[i] == nums[i-1]{ // 去重关键
                continue
            }
            path = append(path, nums[i])
            rec(i+1)
            path = path[:len(path)-1]
        }
    }

    rec(0)

    return res
}

47. Permutations II

👉 LeetCode

Input: nums = [1,1,2]
Output:

[[1,1,2],
[1,2,1], [2,1,1]]

/images/255.jpg

func permuteUnique(nums []int) [][]int {
    sort.Ints(nums) // 去重关键
    var res [][]int
    k := len(nums)
    var rec func([]bool, []int)
    rec = func(used []bool, path []int){
        if len(path) == k{
            res = append(res, append(make([]int, 0, k), path...))
            return
        }

        for i := 0; i < k; i++{
            // skip the used
            if used[i] {
                continue
            }

            // sift the unused and remove the duplicated
            if i > 0 && !used[i-1] && nums[i] == nums[i-1]{
                    continue
            }
            used[i] = true // 加入到path了
            path = append(path, nums[i])
            rec(used, path)
            used[i] = false
            path = path[:len(path)-1]
        }
    }

    rec(make([]bool, k), []int(nil))

    return res
}

51. N-Queens

👉 LeetCode

func solveNQueens(n int) [][]string {
    res := make([][]string, 0)
    var rec func([]bool, []int)
    rec = func(used []bool, path []int){
        if len(path) == n{
            res = append(res, covert(path))
            return
        }

        diagonallyUsed := diagonallyUsed(n, path)
        for i := 0; i < n; i++{
            // 跳过列的位置
            if used[i]{
               continue
            }
            // 跳过斜对角的位置
            if diagonallyUsed[i]{
                continue
            }
            used[i] = true
            path = append(path, i)
            rec(used, path)
            used[i] = false
            path = path[:len(path)-1]
        }
    }

    rec(make([]bool, n), []int(nil))
    return res
}

func covert(path []int)[]string{
    res := make([]string, 0, len(path))
    template := make([]string, 0, len(path))
    for i := 0; i < len(path); i++{
        template = append(template, ".")
    }
    for _, v := range path{
        template[v] = "Q"
        res = append(res, strings.Join(template, ""))
        template[v] = "."
    }
    return res
}

func diagonallyUsed(n int, path []int)[]bool{
    res := make([]bool, n)
    for k, v := range path{
        if i := v - (len(path) - k); i >= 0{
            res[i] = true
        }
        if i := v + (len(path) - k); i <= n-1{
            res[i] = true
        }
    }
    return res
}

Greedy Algorithm

376. Wiggle Subsequence

👉 LeetCode

func wiggleMaxLength(nums []int) int {
    if len(nums) < 2{
        return len(nums)
    }

    res := 1
    preDiff := 0

    for i := 0; i < len(nums) - 1; i++{
        curDiff := nums[i+1] - nums[i]
        if curDiff > 0 && preDiff <= 0 || curDiff < 0 && preDiff >= 0 {
            res++
            preDiff = curDiff
        }
    }

    return res
}

53. Maximum Subarray

👉 LeetCode

Input: nums = [-2,1,-3,4,-1,2,1,-5,4]
Output: 6
Explanation: [4,-1,2,1] has the largest sum = 6.

func maxSubArray(nums []int) int {
    res := nums[0]
    sum := 0
    for i := 0; i < len(nums); i++{
        sum += nums[i]
        if sum > res{
            res = sum
        }
        // 贪心
        // sum < 0时不参与累加
        if sum < 0{
            sum = 0
        }
    }
    return res
}

Dalymic Programing

188. Best Time to Buy and Sell Stock IV

👉 LeetCode

// 最多买卖k次
func maxProfit(k int, prices []int) int {
    k = min(k, len(prices) / 2)
    buy := make([]int, k+1)
    for i := range buy{
        buy[i] = -1<<31
    }
    sell := make([]int, k+1)
    for _, p := range prices{
        for j := 1; j < k+1; j++{
            buy[j] = max(buy[j], sell[j-1]-p)
            sell[j] = max(sell[j], buy[j]+p)
        }
    }
    return sell[len(sell)-1]
}

123. Best Time to Buy and Sell Stock III

👉 LeetCode

// 限定2次
func maxProfit(prices []int) int {
    buy1, sell1, buy2, sell2 := -1<<31, 0, -1<<31, 0
    for _, p := range prices{
        buy1 = max(buy1, 0 - p)
        sell1 = max(sell1, buy1 + p)
        buy2 = max(buy2, sell1 - p)
        sell2 = max(sell2, buy2 + p)
    }
    return sell2
}

122. Best Time to Buy and Sell Stock II

👉 LeetCode

// 不限次
func maxProfit(prices []int) int {
    buy, sell := -1<<31, 0
    for _, p := range prices{
        buy = max(buy, sell - p)
        sell = max(sell, buy + p)
    }
    return sell
}
func maxProfit(prices []int) int {
    cache := make(map[int]int)
    return rec(len(prices)-1, false, prices, cache)
}

func rec(i int, hold bool, prices []int, cache map[int]int)int{
    key := getKey(i, hold)
    if v, ok := cache[key]; ok{
        return v
    }

    if i == 0{
        if hold{
            return -prices[0]
        }else{
            return 0
        }
    }
    if hold{
        cache[key] = max(rec(i-1, true, prices, cache),
                            rec(i-1, false, prices, cache) - prices[i])
        return cache[key]
    }
    cache[key] = max(rec(i-1, false, prices, cache),
                        rec(i-1, true, prices, cache) + prices[i])
    return cache[key]
}

func getKey(i int, hold bool)int{
    if hold{
        return i
    }
    return -i
}

309. Best Time to Buy and Sell Stock with Cooldown

👉 LeetCode

// 不限次+冷冻期
func maxProfit(prices []int) int {
    buy, preSell, sell := -1<<31, 0, 0
    for _, p := range prices{
        buy = max(buy, preSell - p) // buy基于上上一次sell
        sell, preSell = max(sell, buy + p), sell
    }
    return sell
}

714. Best Time to Buy and Sell Stock with Transaction Fee

👉 LeetCode

// 不限次+手续费
func maxProfit(prices []int, fee int) int {
    buy, sell := -1<<31, 0
    for _, p := range prices{
        buy = max(buy, sell - p - fee)
        sell = max(sell, buy + p)
        // 或者
        // buy = max(buy, sell - p)
        // sell = max(sell, buy + p -fee)
    }
    return sell
}

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

416. Partition Equal Subset Sum

👉 LeetCode

// 01背包
// n 商品数量,w 商品体积,v 商品价值, c 背包容量
// 第i个商品选或者不选
// rec(i, c) = max(rec(i-1, c), rec(i-1, c-w[i]) + v[i])

func canPartition(nums []int) bool {
    target := 0
    for _, v := range nums{
        target += v
    }
    if target % 2 != 0{
        return false
    }
    target /= 2
    cache := make(map[string]bool)
    var rec func(int, int)bool
    rec = func(i, c int)bool{
        if i < 0{
            if c == 0{
                return true
            }
            return false
        }
        k := getKey(i, c)
        if _, ok := cache[k]; ok{
            return cache[k]
        }
        if c < nums[i]{
            cache[k] = rec(i-1, c)
            return cache[k]
        }
        cache[k] = rec(i-1, c) || rec(i-1, c-nums[i])
        return cache[k]
    }
    return rec(len(nums)-1, target)
}

func getKey(i, c int)string{
    return string([]rune{rune(i), rune(c)})
}

518. Coin Change 2

👉 LeetCode

// 完全背包
// n 商品数量,w 商品体积,v 商品价值, c 背包容量
// 第i个商品选或者不选且可以重复选
// rec(i, c) = max(rec(i-1, c), rec(i, c-w[i]) + v[i])

func change(amount int, coins []int) int {
    cache := make(map[string]int)
    var rec func(int, int)int
    rec = func(i, c int)int{
        if i < 0{
            if c == 0{
                return 1
            }
            return 0
        }
        k := getKey(i, c)
        if _, ok := cache[k]; ok{
            return cache[k]
        }
        if c < coins[i]{
            cache[k] = rec(i-1, c)
            return cache[k]
        }
        cache[k] = rec(i-1, c) + rec(i, c-coins[i])
        return cache[k]
    }
    return rec(len(coins)-1, amount)
}

func getKey(i, c int)string{
    return string([]rune{rune(i), rune(c)})
}

func change(amount int, coins []int) int {
    n := len(coins) // 商品总数
    dp := make([]int, amount+1)
    dp[0] = 1

    for i := 0; i < n; i++{
        for j := coins[i]; j <= amount; j++{
            dp[j] = dp[j] + dp[j-coins[i]]
        }
    }

    return dp[amount]
}

1049. Last Stone Weight II

👉 LeetCode

func lastStoneWeightII(stones []int) int {
    sum := 0
    for _, v := range stones{
        sum += v
    }

    target := sum/2
    n := len(stones)
    dp := make([]int, target+1)

    for i := 1; i <= n; i++{
        for j := target; j >= stones[i-1]; j--{
            dp[j] = max(dp[j], dp[j-stones[i-1]] + stones[i-1])
        }
    }

    return sum - 2*dp[target]
}

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

494. Target Sum

👉 LeetCode

Input: nums = [1,1,1,1,1], target = 3
Output: 5
Explanation: There are 5 ways to assign symbols to make the sum of nums be target 3.
-1 + 1 + 1 + 1 + 1 = 3
+1 - 1 + 1 + 1 + 1 = 3
+1 + 1 - 1 + 1 + 1 = 3
+1 + 1 + 1 - 1 + 1 = 3
+1 + 1 + 1 + 1 - 1 = 3

// 回溯
func findTargetSumWays(nums []int, target int) int {
    res, total := 0, 0
    for _, v := range nums{
        total += v
    }

    var rec func(int, int)
    rec = func(start, sum int){
        if sum - (total - sum) == target{
            res++
        }
        for i := start; i < len(nums); i++{
            sum += nums[i]
            rec(i+1, sum)
            sum -= nums[i]
        }
    }

    rec(0, 0)

    return res

}

// dp
func findTargetSumWays(nums []int, target int) int {
    total := 0
    for _, v := range nums{
        total += v
    }

    // x - (total - x) = target
    // x = (target + total) / 2

    if (total + target) % 2 != 0{
        return 0
    }

    target = (target + total) / 2
    capicity := target
    if target < 0{
        capicity = -target
    }

    // dp[j] 表示刚好填满容量j的途径的数量
    dp := make([]int, capicity+1)
    dp[0] = 1
    for i := 1; i <= len(nums); i++{
        for j := target; j >= nums[i-1]; j--{
            dp[j] = dp[j] + dp[j-nums[i-1]]
        }
    }

    return dp[capicity]
}

300. Longest Increasing Subsequence

👉 LeetCode

Input: nums = [10,9,2,5,3,7,101,18]
Output: 4
Explanation: The longest increasing subsequence is [2,3,7,101], therefore the length is 4.

// O(nlogn)
// sort.SearchInts(s, v) 返回v在有序数组s中的下标,如果与元素相等,则排在元素前面
func lengthOfLIS(nums []int) int {
    var s []int
    for _, v := range nums{
        i := sort.SearchInts(s, v)
        if i == len(s){
            s = append(s, v)
        }else{
            s[i] = v
        }
    }
    return len(s)
}

// dp
func lengthOfLIS(nums []int) int {
    if len(nums) <= 1{
        return len(nums)
    }
    res := 0
    // dp[i]表示以nums[i]为结尾的LIS,所以dp[i] >= 1
    dp := make([]int, len(nums))
    for i := range dp{
        dp[i] = 1
    }

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

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

718. Maximum Length of Repeated Subarray

👉 LeetCode

Input: nums1 = [1,2,3,2,1], nums2 = [3,2,1,4,7]
Output: 3
Explanation: The repeated subarray with maximum length is [3,2,1].

func findLength(nums1 []int, nums2 []int) int {
    res := 0
    dp := make([][]int, len(nums1)+1)
    for i := range dp{
        dp[i] = make([]int, len(nums2)+1)
    }
    for i, v1 := range nums1{
        for j, v2 := range nums2{
            if v1 == v2{
                dp[i+1][j+1] = dp[i][j] + 1
            }
            if dp[i+1][j+1] > res{
                res = dp[i+1][j+1]
            }
        }
    }
    return res
}

func findLength(nums1 []int, nums2 []int) int {
    res := 0
    dp := make([]int, len(nums2)+1)
    for i := 0; i < len(nums1); i++{
        for j := len(nums2) - 1; j >= 0; j--{ // dp[j+1]依赖前面的元素,必须从大到小遍历
            if nums1[i] == nums2[j]{
                dp[j+1] = dp[j] + 1
            }else{
                dp[j+1] = 0
            }
            if dp[j+1] > res{
                res = dp[j+1]
            }
        }
    }
    return res
}

1143. Longest Common Subsequence

👉 LeetCode

Input: text1 = “abcde”, text2 = “ace”
Output: 3

func longestCommonSubsequence(text1 string, text2 string) int {
    dp := make([][]int, len(text1)+1)
    for i := range dp{
        dp[i] = make([]int, len(text2)+1)
    }
    for i, v1 := range text1{
        for j, v2 := range text2{
            if v1 == v2{
                dp[i+1][j+1] = dp[i][j] + 1
            }else{
                dp[i+1][j+1] = max(dp[i][j+1], dp[i+1][j])
            }
        }
    }
    return dp[len(text1)][len(text2)]
}

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

1035. Uncrossed Lines

👉 LeetCode

Input: nums1 = [1,4,2], nums2 = [1,2,4]
Output: 2
解法同 1143. Longest Common Subsequence #



53. Maximum Subarray

👉 LeetCode

Input: nums = [3,5,-9,1,3,-2,3,4,7,2,-9,6,3,1,-5,4]
Output: 19
Explanation: [1,3,-2,3,47,2,-9,6,3,1] has the largest sum = 19.

func maxSubArray(nums []int) int {
    res := nums[0]
    dp := make([]int, len(nums))
    dp[0] = nums[0] // max subarray ends with nums[0]
    for i := 1; i < len(nums); i++{
        if dp[i-1] > 0{
            dp[i] = dp[i-1] + nums[i] // max subarray ends with nums[i]
        }else{
            dp[i] = nums[i]
        }
        if dp[i] > res{
            res = dp[i]
        }
    }
    return res
}

115. Distinct Subsequences

👉 LeetCode

Input: s = “rabbbit”, t = “rabbit”
Output: 3
Explanation:
As shown below, there are 3 ways you can generate “rabbit” from s.
rabbbit
rabbbit
rabbbit

// dp
func numDistinct(s string, t string) int {
    dp := make([][]int, len(s)+1)
    for i := range dp{
        dp[i] = make([]int, len(t)+1)
        dp[i][0] = 1
    }

    for i, v1 := range s{
        for j, v2 := range t{
            if v1 == v2{
                dp[i+1][j+1] = dp[i][j] + dp[i][j+1]
            }else{
                dp[i+1][j+1] = dp[i][j+1]
            }
        }
    }

    return dp[len(s)][len(t)]
}

// 递归
func numDistinct(s string, t string) int {
    dp := make([][]int, len(s)+1)
    for i := range dp{
        dp[i] = make([]int, len(t)+1)
        for j := range dp[i]{
            dp[i][j] = -1
        }
    }

    var rec func(int, int)int
    rec = func(i, j int)int{
        if j < 0{
            return 1
        }
        if i < 0{
            return 0
        }

        if s[i] == t[j]{
            // return rec(i-1, j-1) + rec(i-1, j)
            if dp[i][j] == -1{
                dp[i][j] = rec(i-1, j-1)
            }
            if dp[i][j+1] == -1{
                dp[i][j+1] = rec(i-1, j)
            }
            return dp[i][j] + dp[i][j+1]
        }else{
            // return rec(i-1, j)
            if dp[i][j+1] == -1{
                dp[i][j+1] = rec(i-1, j)
            }
            return dp[i][j+1]
        }
    }

    return rec(len(s)-1, len(t)-1)
}