算法 - 动规07(Swift版本)

102 阅读2分钟

打家劫舍系列

题目1: 198.打家劫舍

讲解
leetcode

// @lc code=start
class Solution {
    // dp[i] 为第i家及以前所有家 能偷到的最高金额
    func rob(_ nums: [Int]) -> Int {
        if nums.count == 1 { return nums[0] }
        var dp = Array(repeating: 0, count: nums.count)
        dp[0] = nums[0]
        dp[1] = max(nums[0], nums[1])
        for i in 2..<nums.count {
            dp[i] = max(dp[i - 1], dp[i - 2] + nums[i])
        }
        return dp[nums.count - 1]
    }
}
// @lc code=end

题目2:213.打家劫舍II

讲解
leetcode

提供一个思路: 环形问题, 可以舍弃 头或者尾 分别处理最后对比取结果即可。

// @lc code=start
class Solution {
    func rob(_ nums: [Int]) -> Int {
        if nums.count == 0 { return 0 }
        if nums.count == 1 { return nums[0] }

        // 不取首元素 做一次打家劫舍
        // 不取尾元素 做一次打家劫舍
        // 取两个大者
        func robFunc(_ nums: [Int]) -> Int {
            if nums.count == 0 { return 0 }
            if nums.count == 1 { return nums[0] }
            var dp = Array(repeating: 0, count: nums.count)
            dp[0] = nums[0]
            dp[1] = max(nums[1], nums[0])
            for i in 2..<nums.count {
                dp[i] = max(dp[i - 1], dp[i - 2] + nums[i])
            }
            return dp[nums.count - 1]
        }
        var noHead = robFunc(Array(nums[1..<nums.count]))
        var noTail = robFunc(Array(nums[0..<(nums.count - 1)]))
        return max(noHead, noTail)
    }
}
// @lc code=end

题目3:337.打家劫舍 III

讲解
leetcode

熟悉一下树形dp的操作。

// 动态规划
func rob(_ root: TreeNode?) -> Int {
    guard let root else { return 0 }
    // 元祖: 取当前节点, 不取当前节点
    func dfs(_ root: TreeNode?) -> (Int, Int) {
        guard let root else { return (0, 0) }
        let left = dfs(root.left)
        let right = dfs(root.right)
        return (root.val + left.1 + right.1, max(left.0, left.1) + max(right.0, right.1))
    }
    let res = dfs(root)
    return max(res.0, res.1)
}

// 暴力递归搜索,  超时
func rob(_ root: TreeNode?) -> Int {
    guard let root else { return 0 }
    if root.left == nil, root.right == nil {
        return root.val
    }
    var val = root.val
    if let left = root.left {
        val += rob(left.left) + rob(left.right)
    }
    if let right = root.right {
        val += rob(right.left) + rob(right.right)
    }
    var val1 = rob(root.left) + rob(root.right)
    return max(val, val1)
}

//暴力递归搜索
//记忆化搜索

// 使 TreeNode 遵守 Hashable 协议
extension TreeNode: Hashable {
    static public func == (lhs: TreeNode, rhs: TreeNode) -> Bool {
        return lhs.val == rhs.val && lhs.left == rhs.left && lhs.right == rhs.right
    }
    
    public func hash(into hasher: inout Hasher) {
        hasher.combine(val)
        hasher.combine(left)
        hasher.combine(right)
    }
}

var map = [TreeNode: Int]()    
func rob(_ root: TreeNode?) -> Int {
    guard let root else { return 0 }
    if root.left == nil, root.right == nil {
        return root.val
    }
    if let val = map[root] { return val }
    var val = root.val
    if let left = root.left {
        val += rob(left.left) + rob(left.right)
    }
    if let right = root.right {
        val += rob(right.left) + rob(right.right)
    }
    var val1 = rob(root.left) + rob(root.right)
    let res = max(val, val1)
    map[root] = res
    return max(val, val1)
}