Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 3 Current »

LC 2055. Plates Between Candles 蜡烛之间的盘子

https://leetcode.com/problems/plates-between-candles/

func platesBetweenCandles(s string, queries [][]int) []int {
    plates := make([]int, len(s))
    candelsL := make([]int, len(s))
    candelsR := make([]int, len(s))

    candelsR[0] = -1
    for i := 1; i < len(s); i++ {
        if s[i] == '|' { // candel
            plates[i] = plates[i-1]
            candelsR[i] = i
        } else { // plate
            plates[i] = plates[i-1] + 1
            candelsR[i] = candelsR[i-1]
        }
    }

    candelsL[len(s)-1] = -1
    for i := len(s)-2; i >= 0; i-- {
        if s[i] == '|' { // candel
            candelsL[i] = i
        } else { // plate
            candelsL[i] = candelsL[i+1]
        }
    }

    result := make([]int, len(queries))
    for i, q := range queries {
        L := candelsL[q[0]]
        R := candelsR[q[1]]

        if L == -1 || R == -1 || L >= R {
            result[i] = 0
        } else {
            result[i] = plates[R] - plates[L]
        }
    }

    return result
}

预处理前缀和,做到 O(1) 计算一个点右侧的最近蜡烛、左侧的最近蜡烛和两点之间的盘子数

动态规划

动态规划问题的一般形式就是求最值,求解动态规划的核心问题是穷举

  1. 写出暴力解

  2. 利用 memory table / 数组优化暴力解

LC 509. Fibonacci Number 斐波那契数

https://leetcode.com/problems/fibonacci-number

递归解法

func fib(n int) int {
    if n == 0 || n == 1 {
        return n
    }
    
    return fib(n - 1) + fib(n - 2)
}

迭代解法

func fib(n int) int {
    if n == 0 || n == 1 {
        return n
    }
    
    dp := make([]int, n + 1)
    dp[1] = 1
    
    for i := 2; i <= n; i++ {
        dp[i] = dp[i-1] + dp[i-2]
    }
    
    return dp[n]
}

迭代解法(进一步优化空间复杂度)

func fib(n int) int {
    if n == 0 || n == 1 {
        return n
    }
    
    a, b := 0, 1
    
    for i := 2; i <= n; i++ {
        a, b = b, a + b
    }
    
    return b
}

LC 322. 零钱兑换

https://leetcode.com/problems/coin-change

暴力解法(TLE)

func coinChange(coins []int, amount int) int {    
    t := change(coins, amount, 0)
    if t == math.MaxInt {
        return -1
    }
    return t
}

func change(coins []int, amount int, currentTimes int) int {
    if amount == 0 {
        return currentTimes
    }
    
    minTimes := math.MaxInt
    
    for _, coin := range coins {
        balance := amount - coin
        if balance >= 0 {
            minTimes = min(minTimes, change(coins, balance, currentTimes + 1))
        }
    }
    

    return minTimes
}

动态规划

func coinChange(coins []int, amount int) int {    
    dp := make([]int, amount + 1)
    
    for x := 1; x <= amount; x++ {
        minTimes := math.MaxInt
        for _, coin := range coins {
            balance := x - coin
            if balance >= 0 && dp[balance] >= 0 {
                minTimes = min(minTimes, dp[balance] + 1)
            }
        }
        
        if minTimes == math.MaxInt {
            dp[x] = -1
        } else {
            dp[x] = minTimes
        }
    }
    
    // fmt.Println(dp)
    
    return dp[amount]
}

进一步优化常数时间(利用 MAX 代替 IntMax 来减少 if)

func coinChange(coins []int, amount int) int {    
    MAX := amount+1
    dp := make([]int, amount + 1)
    
    for x := 1; x <= amount; x++ {
        dp[x] = MAX
        for _, coin := range coins {
            balance := x - coin
            if balance >= 0 {
                dp[x] = min(dp[x], dp[balance] + 1)
            }
        }
    }
        
    if dp[amount] >= MAX {
        return -1
    }
    
    return dp[amount]
}

回溯

回溯算法和我们常说的 DFS 算法基本可以认为是同一种算法

抽象地说,解决一个回溯问题,实际上就是遍历一棵决策树的过程,树的每个叶子节点存放着一个合法答案。你把整棵树遍历一遍,把叶子节点上的答案都收集起来,就能得到所有的合法答案。

其核心就是 for 循环里面的递归,在递归调用之前「做选择」,在递归调用之后「撤销选择」,特别简单。

LC 46. Permutations 全排列

https://leetcode.com/problems/permutations

func permute(nums []int) (result [][]int) {
    backtrack(&result, nums, make([]int, 0, len(nums)), make(map[int]bool, len(nums)))
    
    return
}

func backtrack(result *[][]int, nums []int, current []int, used map[int]bool) {
    if len(current) == len(nums) {
        *result = append(*result, append([]int(nil), current...))
        return
    }
    
    for _, num := range nums {
        if used[num] {
            continue
        }
        
        current = append(current, num)
        used[num] = true
        
        backtrack(result, nums, current, used)
        
        current = current[:len(current)-1]
        used[num] = false
    }
}

LC 51. N-Queens N 皇后

https://leetcode.com/problems/n-queens/

  • No labels