算法 - 动规06(Swift版本)

75 阅读1分钟

动规背包总结篇

题目1:322. 零钱兑换

讲解
leetcode

// @lc code=start
class Solution {
    // 完全背包 
    // 但是求个数
    func coinChange(_ coins: [Int], _ amount: Int) -> Int {
        var dp = Array(repeating: Int.max, count: amount + 1)
        dp[0] = 0
        for i in coins {
            if amount < i { continue }
            for j in i...amount {
                if dp[j - i] != Int.max {
                    dp[j] = min(dp[j], dp[j - i] + 1)
                }
            }
        }
        return dp[amount] == Int.max ? -1 : dp[amount]
    }
}
// @lc code=end

题目2:279.完全平方数

讲解
leetcode

// @lc code=start
class Solution {
    // n 为背包容量
    // 完全平方数为物品
    // 完全平方数可以选多次, 完全背包类型 - 顺序遍历背包容量
    func numSquares(_ n: Int) -> Int {
        var dp = Array(repeating: Int.max, count: n + 1)
        dp[0] = 0
        // 遍历背包
        for j in 1...n {
            // 物品
            for i in 1...j {
                if j < i * i { break }
                dp[j] = min(dp[j], dp[j - i * i] + 1)
            }
        }
        return dp[n]
    }
}
// @lc code=end

题目3: 139.单词拆分

讲解
leetcode

// 方式1
// 遍历单词,效率高些
class Solution {
    // wordDict中的元素为物品, 可以重复使用,完全背包
    // dp[i]代表 字符串长度为时 是否可以被dic中的单词拼成
    // dp[i] = dp[j] && substring(j, i)是否在dic中
    // dp[0] = true 其他默认是false
    // 顺序有关系,所以是排列。 那么先遍历背包。
    func wordBreak(_ s: String, _ wordDict: [String]) -> Bool {
        var dp = Array(repeating: false, count: s.count + 1)
        dp[0] = true
        for i in 1...s.count { // 背包
            for word in wordDict {
                if i < word.count { continue }
                let end = s.index(s.startIndex, offsetBy: i - 1)
                let start = s.index(s.startIndex, offsetBy: i - word.count)
                let subStr = String(s[start...end])
                if dp[i - word.count], subStr == word {
                    dp[i] = true
                }
            }
        }
        return dp[s.count]
    }
}

//方式2
// 写法简单
class Solution {
    func wordBreak(_ s: String, _ wordDict: [String]) -> Bool {
        var dp = Array(repeating: false, count: s.count + 1)
        dp[0] = true
        for i in 1...s.count { // 背包
            for j in 0..<i {   // 物品
                let start = s.index(s.startIndex, offsetBy: j)
                let end = s.index(s.startIndex, offsetBy: i)
                var subStr = String(s[start..<end])
                if dp[j] && wordDict.contains(subStr) {
                    dp[i] = true
                }
            }
        }
        return dp[s.count]
    }
}