算法 - 动规11(Swift版本)

5 阅读2分钟

题目1:1143.最长公共子序列

讲解
leetcode

class Solution {
    func longestCommonSubsequence(_ text1: String, _ text2: String) -> Int {
        // 写法类似于 718. 最长重复子数组
        var dp = Array(repeating: Array(repeating: 0, count: text2.count + 1), count: text1.count + 1)
        var text1Arr = Array(text1)
        var text2Arr = Array(text2)
        var result = 0
        for i in 1...text1Arr.count {
            for j in 1...text2Arr.count {
                if text1Arr[i - 1] == text2Arr[j - 1] {
                    dp[i][j] = dp[i - 1][j - 1] + 1
                } else {
                    dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])
                }
            }
        }
        return dp[text1.count][text2.count]
    }
}

题目2:1035.不相交的线

讲解
leetcode

很典型的一个最长公共子序列的 应用题描述。
可以尝试自己再理解下,看是否能推导到 最长公共子序列的题目上面去。

class Solution {
    func maxUncrossedLines(_ nums1: [Int], _ nums2: [Int]) -> Int {
        // 不相交 - 等于 1143. 最长公共子串
        var dp = Array(repeating: Array(repeating: 0, count: nums2.count + 1), count: nums1.count + 1)
        for i in 1...nums1.count {
            for j in 1...nums2.count {
                if nums1[i - 1] == nums2[j - 1] {
                    dp[i][j] = dp[i - 1][j - 1] + 1
                } else {
                    dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])
                }
            }
        }
        return dp[nums1.count][nums2.count]
    }
}

题目3:53. 最大子数组和

讲解
leetcode

class Solution {
    /*
    // 贪心
    func maxSubArray(_ nums: [Int]) -> Int {
        var res = -Int.max
        var sum = 0 
        for i in 0..<nums.count {
            sum += nums[i]
            res = max(res, sum)
            if sum < 0 { sum = 0 }
        }
        return res
    }
    */
    // 动规
    func maxSubArray(_ nums: [Int]) -> Int {
        if nums.count == 1 { return nums[0] }
        var dp = Array(repeating: 0, count: nums.count)
        dp[0] = nums[0]
        var result = dp[0]
        for i in 1..<nums.count {
            // 要么连续序列, 要么从自己从头。
            dp[i] = max(nums[i], dp[i - 1] + nums[i])
            result = max(result, dp[i])
        }
        return result
    }
}

题目4:392.判断子序列

讲解
leetcode

实际上这个题目 还是1143. 最长公共子序列题目。
按照 那个题目写 一点问题没有。
这里之所以可以简化成dp[i][j] = dp[i][j - 1],是因为已经明确了判断 s是否是t的子串,所以单独删除t的字符 也是没问题的。

class Solution {
    func isSubsequence(_ s: String, _ t: String) -> Bool {
        // 简化相当于求 最长公共子串。
        // 只不过当不一致的时候,只删t的字符。
        if s.count == 0 { return true }
        if t.count == 0 { return false }
        var dp = Array(repeating: Array(repeating: 0, count: t.count + 1), count: s.count + 1)
        var ss = Array(s)
        var ts = Array(t)
        for i in 1...s.count {
            for j in 1...t.count {
                if ss[i - 1] == ts[j - 1] {
                    dp[i][j] = dp[i - 1][j - 1] + 1
                } else {
                    // 相当于舍弃t的字符  得到的最长公共子串。
                    dp[i][j] = dp[i][j - 1]
                }
            }
        }
        return dp[s.count][t.count] == s.count
    }
}