LeetCode 刷题集 - 动态规划(4)

动态规划定义

初识动态规划:如何巧妙解决双十一购物时的凑单问题?

动态规划理论:一篇文章带你彻底搞懂最优子结构、无后效性和重复子问题

动态规划实战:如何实现搜索引擎中的拼写纠错功能?

递归代码模板

分治代码模板

动态规划定义

MIT 动态规划课程最短路径算法

LeetCode题目:

1.最长公共子序列

class Solution {
    func longestCommonSubsequence(_ text1: String, _ text2: String) -> Int {
        let text1Arr = Array(text1), text2Arr = Array(text2)
        let m = text1.count, n = text2.count
        // 构造二维数组 全0
        var arr = Array(repeating: Array(repeating: 0, count: m + 1), count: n + 1)
        for i in 1..<arr.count {
            for j in 1..<arr.first!.count {
                if text1Arr[j - 1] == text2Arr[i - 1] {
                    arr[i][j] = 1 + arr[i - 1][j - 1]
                } else {
                    arr[i][j] = max(arr[i - 1][j], arr[i][j - 1])
                }
            }
        }
        return arr[n][m]
    }
}

2.三角形最小路径和

-Bottom-Up 技巧是从倒数第二层开始递推

class Solution {
    func minimumTotal(_ triangle: [[Int]]) -> Int {
        var dp = triangle
        for i in (0..<dp.count - 1).reversed() {
            for j in 0..<dp[i].count {
                dp[i][j] += min(dp[i + 1][j], dp[i + 1][j + 1])
            }
        }
        return dp[0][0]
    }
}

-Up-Bottom 递归加记忆化搜索

class Solution {
        var memDict = Dictionary<String, Int>()
        func minimumTotal(_ triangle: [[Int]]) -> Int {
            return helper(i: 0, j: 0, triangle: triangle)
        }
        func helper(i: Int, j: Int, triangle: [[Int]]) -> Int{
            if i == triangle.count - 1 {
                return triangle[i][j]
            }
            guard memDict["\(i) * \(j)"] != nil else {
                let left = helper(i: i + 1, j: j, triangle: triangle)
                let right = helper(i: i + 1, j: j + 1, triangle: triangle)
                memDict["\(i) * \(j)"] = min(left, right) + triangle[i][j]
                return memDict["\(i) * \(j)"]!
            }
            return memDict["\(i) * \(j)"]!
        }
}

3.不同路径

-Bottom-Up DP方程递推出最终结果

class Solution {
   func uniquePaths(_ m: Int, _ n: Int) -> Int {
        if m == 1 || n == 1 {
            return 1
        }
        var arr = Array(repeating: Array(repeating: 0, count: n), count: m)
        for i in 0..<n {
            arr[m - 1][i] = 1
        }
        for j in 0..<m {
            arr[j][n - 1] = 1
        }
        var i = m - 2, j = n - 2
        repeat {
            arr[i][j] = arr[i + 1][j] + arr[i][j + 1]
            if i == 0 && j == 0 {
                break
            }
            if i != 0 {
                i -= 1
            } else {
                i = m - 2
                j -= 1
            }
        } while true
       return arr[0][0]
    }
}

-Up-Bottom* 递归 + 记忆化搜索

class Solution {
    var memDict: Dictionary<String, Int> = Dictionary<String, Int>()
   func uniquePaths(_ m: Int, _ n: Int) -> Int {
        return countPath(m: m, n: n, row: 0, col: 0)
    }
    func countPath(m: Int, n: Int, row: Int, col: Int) -> Int {
        if !validSqure(m: m, n: n, row: row, col: col) { return 0 }
        if isAtEnd(m: m, n: n, row: row, col: col) { return 1 }
        //memoize
        guard memDict["\(row) * \(col)"] != nil else {
            memDict["\(row) * \(col)"] = countPath(m: m, n: n, row: row + 1, col: col) + countPath(m: m, n: n, row: row, col: col + 1)
            return memDict["\(row) * \(col)"]!
        }
        return memDict["\(row) * \(col)"]!
    }
    func validSqure(m: Int, n: Int, row: Int, col: Int) -> Bool {
        if row > m - 1 { return false }
        if col > n - 1 { return false }
        return true
    }
    func isAtEnd(m: Int, n: Int, row: Int, col: Int) -> Bool {
        if row == m - 1 { return true }
        if col == n - 1 { return true }
        return false
    }
}

4.不同路径 II

-Up-Bottom* 递归并处理特殊情况

class Solution {
       var memDict: Dictionary<String, Int> = Dictionary<String, Int>()
        func uniquePathsWithObstacles(_ obstacleGrid: [[Int]]) -> Int {
            guard obstacleGrid[obstacleGrid.count - 1][obstacleGrid.first!.count - 1] != 1 else { return 0 }
            // 横条
            if obstacleGrid.count == 1 {
                if obstacleGrid.first!.contains(1) {
                    return 0
                } else {
                    return 1
                }
            }
            // 竖条
            if obstacleGrid.first!.count == 1 {
                for arr in obstacleGrid {
                    if arr.first == 1 {
                        return 0
                    }
                }
                return 1
            }
            return countPath(grid: obstacleGrid, i: 0, j: 0)
        }
        func countPath(grid: [[Int]], i: Int, j: Int) -> Int {
            if !validCourt(grid: grid, i: i, j: j) { return 0 }
            if grid[i][j] == 1 { return 0}
            if isAtEnd(grid: grid, i: i, j: j) {
                if hasBarrierBehind(grid: grid, i: i, j: j) {
                    return 0
                } else {
                    return 1
                }
            }
            
            guard memDict["\(i) * \(j)"] != nil else {
                memDict["\(i) * \(j)"] = countPath(grid: grid, i: i, j: j + 1) + countPath(grid: grid, i: i + 1, j: j)
                return memDict["\(i) * \(j)"]!
            }
            return memDict["\(i) * \(j)"]!
        }
        func validCourt(grid: [[Int]], i: Int, j: Int) -> Bool {
            if (i > grid.count - 1) || (j > grid.first!.count - 1) {
                return false
            }
            return true
        }
        func isAtEnd(grid: [[Int]], i: Int, j: Int) -> Bool {
            if (i == grid.count - 1) || (j == grid.first!.count - 1) {
                return true
            }
            return false
        }
        func hasBarrierBehind(grid: [[Int]], i: Int, j: Int) -> Bool {
            if j == grid.first!.count - 1 {
                //右边竖条
                for k in i...grid.count - 1 {
                    if grid[k][grid.first!.count - 1] == 1 {
                        return true
                    }
                }
            } else {
                //底下横条
                for k in j...grid.first!.count - 1 {
                    if grid[grid.count - 1][k] == 1 {
                        return true
                    }
                }
            }
            return false
        }
}

-Bottom-Up DP*方程递推出结果先给两边处理了然后正常递推

class Solution {
    func uniquePathsWithObstacles(_ obstacleGrid: [[Int]]) -> Int {
        guard obstacleGrid[obstacleGrid.count - 1][obstacleGrid.first!.count - 1] != 1 else {
            return 0
        }
        // 横条
        if obstacleGrid.count == 1 {
            if obstacleGrid.first!.contains(1) {
                return 0
            } else {
                return 1
            }
        }
        // 竖条
        if obstacleGrid.first!.count == 1 {
            for arr in obstacleGrid {
                if arr.first == 1 {
                    return 0
                }
            }
            return 1
        }
        var arr = obstacleGrid
        let m = arr.count, n = arr.first!.count
        for i in 0..<n - 1 {
            if arr[m - 1][i] == 1 {
                // 前边都得置0
                for j in 0...i {
                    arr[m - 1][j] = 0
                }
            } else {
                arr[m - 1][i] ^= 1
            }
            
        }
        for j in 0..<m - 1 {
            if arr[j][n - 1] == 1 {
                // 前边都得置0
                for i in 0...j {
                    arr[i][n-1] = 0
                }
            } else {
                arr[j][n - 1] ^= 1
            }
        }
        var i = m - 2, j = n - 2
        repeat{
            if arr[i][j] == 1 {
                arr[i][j] = 0
            } else {
                arr[i][j] = arr[i][j + 1] + arr[i + 1][j]
            }
            if i == 0 && j == 0 {
                break
            }
            if i != 0 {
                i -= 1
            } else {
                i = m - 2
                j -= 1
            }
        } while true
         
        return arr[0][0]
    }
}

5.不同路径 III


6.最长递增子序列

class Solution {
func lengthOfLIS(_ nums: [Int]) -> Int {
        guard nums.count > 1 else {
            return 1
        }
        var dpArr = Array(repeating: 1, count: nums.count)
        var res = 0
        for i in 1..<dpArr.count {
            for j in 0..<i {
                if nums[i] > nums[j] {
                    dpArr[i] = max(dpArr[i], dpArr[j] + 1)
                }
            }
            res = max(dpArr[i], res)
        }
        return res
    }
}

7.打家劫舍

-升维DP

class Solution {
    func rob(_ nums: [Int]) -> Int {
        guard nums.count > 0 else {
            return 0
        }
        var dpArr = Array(repeating: Array(repeating: 0, count: 2), count: nums.count)
        dpArr[0][0] = 0
        dpArr[0][1] = nums[0]
        for i in 1..<nums.count {
            dpArr[i][0] = max(dpArr[i - 1][0], dpArr[i - 1][1])
            dpArr[i][1] = nums[i] + dpArr[i - 1][0]
        }
        return max(dpArr[nums.count - 1][0], dpArr[nums.count - 1][1])
    }
}

-不升维DP

class Solution {
    func rob(_ nums: [Int]) -> Int {
        guard nums.count > 0 else {
            return 0
        }
        if nums.count == 1 {
            return nums[0]
        }
        var dpArr = Array(repeating: 0, count: nums.count)
        dpArr[0] = nums[0]
        dpArr[1] = max(nums[0], nums[1])
        for i in 2..<nums.count {
            dpArr[i] = max(dpArr[i - 1], dpArr[i - 2] + nums[i])
        }
        return dpArr[nums.count - 1]
    }
}

-优化掉不升维DP中的数组

class Solution {
    func rob(_ nums: [Int]) -> Int {
        var pre = 0
        var now = 0
        for i in nums {
            let temp = max(pre + i, now)
            pre = now
            now = temp
        }
        return now
    }
}

8.打家劫舍 II

class Solution {
//首尾相连,就他它转化成两个分别来求,最后取大的
func rob(_ nums: [Int]) -> Int {
        var nums = nums
        guard nums.count > 0 else {
            return 0
        }
        if nums.count == 1 {
            return nums[0]
        }
        if nums.count == 2 {
            return max(nums.first!, nums.last!)
        }
        let tempLast = nums.removeLast()
        let dpArrContainFirst = nums
        nums = nums + [tempLast]
        let tempFirst = nums.removeFirst()
        let dpArrContainLast = nums
        nums = [tempFirst] + nums
        var dpArr1 = Array(repeating: 0, count: dpArrContainFirst.count)
        dpArr1[0] = dpArrContainFirst[0]
        dpArr1[1] = max(dpArrContainFirst[0], dpArrContainFirst[1])
        for i in 2..<dpArrContainFirst.count {
            dpArr1[i] = max(dpArr1[i - 1], dpArr1[i - 2] + dpArrContainFirst[i])
        }
        var dpArr2 = Array(repeating: 0, count: dpArrContainLast.count)
        dpArr2[0] = dpArrContainLast[0]
        dpArr2[1] = max(dpArrContainLast[0], dpArrContainLast[1])
        for i in 2..<dpArrContainLast.count {
            dpArr2[i] = max(dpArr2[i - 1], dpArr2[i - 2] + dpArrContainLast[i])
        }
        return max(dpArr1.last!, dpArr2.last!)
    }
}

9.零钱兑换

-DP

class Solution {
    func coinChange(_ coins: [Int], _ amount: Int) -> Int {
        guard amount > 0 else {
            return 0
        }
        var dpArr = Array(repeating: amount + 1, count: amount + 1)
        dpArr[0] = 0
        for i in 1...amount {
            for j in 0..<coins.count {
                if coins[j] <= i {
                    dpArr[i] = min(dpArr[i], dpArr[i - coins[j]] + 1)
                }
            }
        }
        return dpArr[amount] > amount ? -1 : dpArr[amount]
    }
}

-超出时间限制的DFS + 回溯

func coinChange(_ coins: [Int], _ amount: Int) -> Int {
        var res = Array<Int>()
        var curCoinArray = Array<Int>()
        dfs(coins: coins.sorted(by: >), amount: amount, cur: 0, res: &res, curCoinArray: &curCoinArray)
        return res.count == 0 ? -1 : res.first!
    }
    func dfs(coins: [Int], amount: Int, cur: Int, res: inout Array<Int>, curCoinArray: inout [Int]) {
        if cur == amount {
            if res.count != 0 {
                if res.first! >= curCoinArray.count {
                    res.removeFirst()
                    res.append(curCoinArray.count)
                }
            } else {
                res.append(curCoinArray.count)
            }
            return
        }
        if cur > amount { return }
        for (index, i) in coins.enumerated() {
            curCoinArray.append(coins[index])
            dfs(coins: coins, amount: amount, cur: cur + i, res: &res, curCoinArray: &curCoinArray)
            curCoinArray.removeLast()
        }
    }

10.零钱兑换 II

-DP

class Solution {
    func change(_ amount: Int, _ coins: [Int]) -> Int {
        if amount == 0 {
            return 1
        }
        var dpArr = Array(repeating: 0, count: amount + 1)
        dpArr[0] = 1
        for coin in coins {
            if coin > amount { continue }
            for x in coin...amount {
                dpArr[x] += dpArr[x - coin]
            }
        }
        return dpArr.last!
    }
}

-超时的DFS 不好再继续优化(剪枝条件不好找)

class Solution {
    func change(_ amount: Int, _ coins: [Int]) -> Int {
        var res = Set<Array<Int>>()
        var cur = Array<Int>()
        dfs(amount: amount, coints: coins, res: &res, cur: &cur)
        return res.count
    }
    func dfs(amount: Int, coints: [Int], res: inout Set<Array<Int>>, cur: inout [Int]) {
        if amount == 0 {
            res.insert(cur.sorted())
            return
        }
        if amount < 0 {
            return
        }
        for i in coints {
            cur.append(i)
            dfs(amount: amount - i, coints: coints, res: &res, cur: &cur)
            cur.removeLast()
        }
    }
}

11.买卖股票的最佳时机

class Solution {
func maxProfit(_ prices: [Int]) -> Int {
        let prices = [0] + prices
        var dpArr = Array(repeating: Array(repeating: 0, count: 2), count: prices.count)
        dpArr[0][0] = 0
        dpArr[0][1] = Int(-1000000000)
        for i in 1...prices.count - 1 {
            for j in 0...1 {
                if j == 0 {
                    dpArr[i][j] = max(dpArr[i - 1][1] + prices[i], dpArr[i - 1][0])
                } else {
                    // j == 1
                    dpArr[i][j] = max(-prices[i], dpArr[i - 1][1])
                }
            }
        }
        return dpArr[prices.count - 1][0]
    }
}

12.买卖股票的最佳时机 II

-DP

class Solution {
func maxProfit(_ prices: [Int]) -> Int {
        let prices = [0] + prices
        var dpArr = Array(repeating: Array(repeating: 0, count: 2), count: prices.count)
        dpArr[0][0] = 0
        dpArr[0][1] = Int(-1000000)
        for i in 1...prices.count - 1 {
            for j in 0...1 {
                if j == 0 {
                    dpArr[i][j] = max(dpArr[i - 1][1] + prices[i], dpArr[i - 1][0])
                } else {
                    dpArr[i][j] = max(dpArr[i - 1][0] - prices[i], dpArr[i - 1][1])
                }
            }
        }
        return dpArr[prices.count - 1][0]
    }
}

贪心


class Solution {
    func maxProfit(_ prices: [Int]) -> Int {
        var everyProfit = 0
        var res = 0
        for (index, i) in prices.enumerated() {
            if index == prices.count - 1 {
                break
            }
            everyProfit = prices[index + 1] - i
            if everyProfit > 0 {
                res += everyProfit
            }
        }
        return res
    }
}

13.买卖股票的最佳时机 III

class Solution {
func maxProfit(_ prices: [Int]) -> Int {
        let usePrices = [0] + prices
        var dpArr = Array(repeating: Array(repeating: Array(repeating: 0, count: 2), count: 3), count: usePrices.count)
        dpArr[0][0][0] = 0
        dpArr[0][0][1] = -1000000
        dpArr[0][1][0] = 0
        dpArr[0][1][1] = -1000000
        dpArr[0][2][0] = 0
        dpArr[0][2][1] = -1000000
        for i in 1..<usePrices.count {
            for k in 1...2 {
                for o in 0...1 {
                    if o == 0 {
                        dpArr[i][k][0] = max(dpArr[i - 1][k][0], dpArr[i - 1][k][1] + usePrices[i])
                    } else {
                        dpArr[i][k][1] = max(dpArr[i - 1][k][1], dpArr[i - 1][k - 1][0] - usePrices[i])
                    }
                }
            }
        }
        return dpArr[usePrices.count - 1][2][0]
    }
}

14.最佳买卖股票时机含冷冻期

class Solution {
func maxProfit(_ prices: [Int]) -> Int {
        let prices = [0] + prices
        var dpArr = Array(repeating: Array(repeating: 0, count: 2), count: prices.count)
        dpArr[0][0] = 0
        dpArr[0][1] = -10000000
        for i in 1...prices.count - 1 {
            for j in 0...1 {
                if j == 0 {
                    dpArr[i][j] = max(dpArr[i - 1][1] + prices[i], dpArr[i - 1][0])
                } else {
                    // j == 1
                    dpArr[i][j] = max(dpArr[i - 1][0] - prices[i], dpArr[i - 1][1])
                }
            }
        }
        return dpArr[prices.count - 1][0]
    }
}

15.买卖股票的最佳时机 IV

class Solution {
    func maxProfit(_ k: Int, _ prices: [Int]) -> Int {
        guard k > 0 else {
            return 0
        }
        let usePrices = [0] + prices
        var dpArr = Array(repeating: Array(repeating: Array(repeating: 0, count: 2), count: k + 1), count: usePrices.count)
        for i in 0...k {
            for j in 0...1 {
                if j == 0 {
                    dpArr[0][i][j] = 0
                } else {
                    dpArr[0][i][j] = -1000000
                }
            }
        }
        for i in 1..<usePrices.count {
            for j in 1...k {
                for o in 0...1 {
                    if o == 0 {
                           dpArr[i][j][0] = max(dpArr[i - 1][j][0], dpArr[i - 1][j][1] + usePrices[i])
                      } else {
                           dpArr[i][j][1] = max(dpArr[i - 1][j][1], dpArr[i - 1][j - 1][0] - usePrices[i])
                       }
                   }
               }
           }
           return dpArr[usePrices.count - 1][k][0]
       }
}

16.买卖股票的最佳时机含手续费

class Solution {
    func maxProfit(_ prices: [Int], _ fee: Int) -> Int {
            let prices = [0] + prices
            var dpArr = Array(repeating: Array(repeating: 0, count: 2), count: prices.count)
            dpArr[0][0] = 0
            dpArr[0][1] = Int(-1000000)
            for i in 1...prices.count - 1 {
                for j in 0...1 {
                    if j == 0 {
                        dpArr[i][j] = max(dpArr[i - 1][1] + prices[i], dpArr[i - 1][0])
                    } else {
                        dpArr[i][j] = max(dpArr[i - 1][0] - prices[i] - fee, dpArr[i - 1][1])
                    }
                }
            }
            return dpArr[prices.count - 1][0]
        }
}

17.完全平方数

class Solution {
func numSquares(_ n: Int) -> Int {
        var dpArr = Array(repeating: 0, count: n + 1)
        let sqrtN = Int(sqrt(Double(n)))
        dpArr[0] = 0
        for i in 1...n {
            dpArr[i] = i
            for j in 1...sqrtN {
                if i - j * j >= 0 {
                    dpArr[i] = min(dpArr[i], dpArr[i - j * j] + 1)
                }
            }
        }
        return dpArr.last!
    }
}

18.编辑距离(重点)

class Solution {
func minDistance(_ word1: String, _ word2: String) -> Int {
        if word1 == "" || word2 == "" {
            return max(word1.count, word2.count)
        }
        let word1Arr = Array(word1)
        let word2Arr = Array(word2)
        var dpArr = Array(repeating: Array(repeating: 0, count: word2Arr.count + 1), count: word1Arr.count + 1)
        // 哨兵初始化
        for i in 0...word2Arr.count {
            dpArr[0][i] = i
        }
        for i in 0...word1Arr.count {
            dpArr[i][0] = i
        }

        for i in (1...word1Arr.count) {
            for j in (1...word2Arr.count) {
                if word1Arr[i - 1] == word2Arr[j - 1] {
                    dpArr[i][j] = dpArr[i - 1][j - 1]
                } else {
                    dpArr[i][j] = min(dpArr[i][j - 1] + 1, dpArr[i - 1][j] + 1, dpArr[i - 1][j - 1] + 1)
                }
            }
        }
        return dpArr[word1.count][word2.count]
    }
}

19.跳跃游戏

-DP

class Solution {
func canJump(_ nums: [Int]) -> Bool {
        guard nums.count > 1 else {
            return true
        }
        if nums.count == 2 {
            return nums.first! >= 1 ? true : false
        }
        if nums.first! == 0 {
            return false
        }
        var dpArr = nums
        var res = 0
        for i in 1..<nums.count - 1 {
            dpArr[i] = max(dpArr[i - 1], i + nums[i])
            if dpArr[i] == i {
                return false
            }
            res = max(res, dpArr[i])
        }
        return (res >= nums.count - 1) ? true : false
    }
}

-贪心

class Solution {
    func canJump(_ nums: [Int]) -> Bool {
        if nums.count == 1 {
            return true
        }
        var cover = 0
        var i = 0
        while cover < nums.count - 1 {
            if i > cover {
                return false
            }
            cover = max(i + nums[i], cover)
            i += 1
        }
        return true
    }
}

20.跳跃游戏 II

-DP

class Solution {
func jump(_ nums: [Int]) -> Int {
        if nums.count == 1 {
            return 0
        }
        if nums.count == 2 {
            return 1
        }
        var dpArr = Array(repeating: 10000000, count: nums.count)
        dpArr[0] = 0
        var cover = nums.first!
        for i in 1..<nums.count {
            if cover > nums.count - 1 {
                cover = nums.count - 1
            }
            for j in i...cover {
                dpArr[j] = min(dpArr[i - 1] + 1, dpArr[j])
            }
            cover = max(cover, i + nums[i])
        }
        return dpArr.last!
    }
}

贪心

class Solution {
var level = 0
        func jump(_ nums: [Int]) -> Int {
            guard nums.count > 1 else {
                return 0
            }
            var cover = 0
            var i = 0
            while cover < nums.count - 1 {
                cover = max(cover, i + nums[i])
                i += 1
            }
            level += 1
            jump(Array(nums[0...i - 1]))
            return level
        }
}

21.乘积最大子数组

class Solution {
func maxProduct(_ nums: [Int]) -> Int {
        guard nums.count > 1 else {
            return nums.first!
        }
        var res = -100000000
        var dpArr = Array(repeating: Array(repeating: 0, count: 2), count: nums.count + 1)
        dpArr[0][0] = 1
        dpArr[0][1] = 1
        for i in 1...nums.count {
            dpArr[i][0] = nums[i - 1]
            dpArr[i][1] = nums[i - 1]
        }
        for i in 1..<dpArr.count {
            for j in 0...1 {
                if j == 0 {
                    // positive
                    dpArr[i][j] = max(dpArr[i - 1][0] * nums[i - 1], dpArr[i - 1][1] * nums[i - 1], nums[i - 1])
                    res = max(res, dpArr[i][j])
                } else {
                    // negtive
                    dpArr[i][j] = min(dpArr[i - 1][0] * nums[i - 1], dpArr[i - 1][1] * nums[i - 1], nums[i - 1])
                }
            }
        }
        return res
    }
}

22.最小路径和

class Solution {
func minPathSum(_ grid: [[Int]]) -> Int {
        var dpArr = grid
        for i in 1..<grid.count {
            dpArr[i][0] = dpArr[i - 1][0] + dpArr[i][0]
        }
        for i in 1..<grid.first!.count {
            dpArr[0][i] = dpArr[0][i - 1] + dpArr[0][i]
        }
        for i in 1..<dpArr.count {
            for j in 1..<dpArr.first!.count {
                dpArr[i][j] = min(dpArr[i - 1][j], dpArr[i][j - 1]) + dpArr[i][j]
            }
        }
        return dpArr[dpArr.count - 1][dpArr.first!.count - 1]
    }
}

23.最大子序和

class Solution {
func maxSubArray(_ nums: [Int]) -> Int {
        guard nums.count > 1 else {
            return nums.first!
        }
        var dpArr = [-1000000] + nums
        var res = -1000000
        for i in 1..<dpArr.count {
            dpArr[i] = max(dpArr[i - 1] + dpArr[i], dpArr[i])
            res = max(res, dpArr[i])
        }
        return Int(res)
    }
}

24.最大正方形

class Solution {
    func maximalSquare(_ matrix: [[Character]]) -> Int {
        var dpArr = Array(repeating: Array(repeating: 0, count: matrix.first!.count + 1), count: matrix.count + 1)
        var res = 0
        for i in 1..<dpArr.count {
            for j in 1..<dpArr.first!.count {
                if matrix[i - 1][j - 1] == "1" {
                    dpArr[i][j] = min(dpArr[i - 1][j], dpArr[i - 1][j - 1], dpArr[i][j - 1]) + 1
                    res = max(res, dpArr[i][j])
                }
            }
        }
        return res * res
    }
}

25.青蛙过河

class Solution {
    func canCross(_ stones: [Int]) -> Bool {
        if stones.count == 2 {
            if stones.last! > 1 {
                return false
            } else {
                return true
            }
        }
        var dict: Dictionary<Int, Set<Int>> = Dictionary<Int, Set<Int>>()
        dict.updateValue([1], forKey: stones[1] + 1)
        dict.updateValue([2], forKey: stones[1] + 2)
        for i in stones[2...] {
            guard let setValue = dict[i] else {
                continue
            }
            for s in setValue {
                if var set1 = dict[i + s - 1] {
                    set1.insert(s - 1)
                    dict[i + s - 1] = set1
                } else {
                    dict.updateValue( [s - 1], forKey: i + s - 1)
                }
                if var set2 = dict[i + s] {
                    set2.insert(s)
                    dict[i + s] = set2
                } else {
                    dict.updateValue([s], forKey: i + s)
                }
                if var set3 = dict[i + s + 1] {
                    set3.insert(s + 1)
                    dict[i + s + 1] = set3
                } else {
                    dict.updateValue([s + 1], forKey: i + s + 1)
                }
            }
        }
        if dict.keys.contains(stones.last!) {
            return true
        } else {
            return false
        }
    }
}

26.解码方法


27.任务调度器


28.最长有效括号

class Solution {
    func longestValidParentheses(_ s: String) -> Int {
        guard s.count >= 2 else {
            return 0
        }
        let sArr = Array(s)
        var dpArr = Array(repeating: 0, count: s.count)
        var res = 0
        for i in 1..<sArr.count {
            if sArr[i] == "(" {
                dpArr[i] = 0
            } else {
                // ")"
                if sArr[i - 1] == "(" {
                    // 匹配上了 ".....()"
                    if i - 2 > 0 {
                        // sArr[i - 2]存在
                        dpArr[i] = 2 + dpArr[i - 2]
                    } else {
                        // sArr[i - 2]不存在
                        dpArr[i] = 2
                    }
                    
                } else {
                    // 没匹配上 ")" ".....))" 考察 sArr[i - dp[i - 1] -1]
                    if i - dpArr[i - 1] - 1 < 0 {
                        // sArr[i - dpArr[i - 1] -1] 不存在
                        dpArr[i] = 0
                    } else {
                        // sArr[i - dpArr[i - 1] -1] 存在
                        if sArr[i - dpArr[i - 1] - 1] == ")" {
                            // "...).....))"
                            dpArr[i] = 0
                        } else {
                            // "...(.....))" 考察 sArr[i - dpArr[i - 1] - 2]
                            if i - dpArr[i - 1] - 2 < 0 {
                                // sArr[i - dpArr[i - 1] - 2] 不存在
                                dpArr[i] = 2 + dpArr[i - 1]
                            } else {
                                // sArr[i - dp[i - 1] - 2] 存在
                                dpArr[i] = 2 + dpArr[i - 1] + dpArr[i - dpArr[i - 1] - 2]
                            }
                        }
                    }
                }
            }
            res = max(res, dpArr[i])
        }
        return res
    }
}

29.矩形区域不超过 K 的最大数值和


30.分割数组的最大值


31.学生出勤记录 II


32.戳气球


33.使用最小花费爬楼梯


34.最大矩形


35. 不同的子序列


36.赛车


©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容