算法 - 回溯03(Swift版本)

75 阅读2分钟

题目1: 93.复原IP地址

讲解     
leetcode

// @lc code=start
class Solution {
    var result = [String]()
    var set = [String]()
    func restoreIpAddresses(_ s: String) -> [String] {
        restoreIpRecursive(s, 0, "")
        return result
    }

    func restoreIpRecursive(_ s: String, _ start: Int, _ sumStr: String) {
        if set.count >= 4 {
            if set.count == 4, sumStr == s {
                result.append(set.joined(separator: "."))
            }
            return
        }
        for i in start..<s.count {
            // 剪枝: 大于三位,这层就不用再遍历了
            if (i - start + 1) > 3 { break }
            let startIndex = s.index(s.startIndex, offsetBy: start)
            let endIndex = s.index(s.startIndex, offsetBy: i + 1)
            let subString = String(s[startIndex..<endIndex])
            // 这里如果当前这层子串已经不满足,后续追加也是不满足,所以直接break
            if !isValidIpPart(subString) {
                break
            }
            set.append(subString)
            restoreIpRecursive(s, i + 1, sumStr + subString)
            set.removeLast()
        }
    }

    func isValidIpPart(_ s: String) -> Bool {
        if s.count > 3 { return false }
        if s.count > 1, Int(String(s.first!)) ?? 0 == 0 { return false }
        let num = Int(s) ?? 0
        if num == 0, s.count != 1 {
            return false
        }
        return num <= 255
    }
}
// @lc code=end

题目2:78.子集

讲解     
leetcode

// @lc code=start
// 数组元素不会重复 就不用考虑树层重复的问题了
class Solution {
    var result = [[Int]]()
    var set = [Int]()
    func subsets(_ nums: [Int]) -> [[Int]] {
        subsetsRecursive(nums, 0)
        return result
    }
    
    func subsetsRecursive(_ nums: [Int], _ start: Int) {
        result.append(set)
        if start == nums.count { return } 
        for i in start..<nums.count {
            set.append(nums[i])
            subsetsRecursive(nums, i + 1)
            set.removeLast()
        }
    }
}
// @lc code=end

题目3:90.子集II

讲解     
leetcode

// @lc code=start
// 类似组合二问题 https://leetcode.cn/problems/combination-sum-ii/
// 需要树层去重
// 加深下去重理解
// 所以我们要去重的是同一树层上的“使用过”,同一树枝上的都是一个组合里的元素,不用去重。
// 同一树层的元素呢: 
//  1. 首先我们是组合 不是排列,所以只会向后做组合。不用考虑元素往前查找的问题。
//  2. 既然是取某个元素和其他元素做组合, 那这一层上和我紧挨着的元素是相同的, 那么意味着后面的结果完全是重复的。 除了他两个本身的组合,实际上就是情况1,不用考虑。
class Solution {
    var result = [[Int]]()
    var set = [Int]()
    func subsetsWithDup(_ nums: [Int]) -> [[Int]] {
        subsetsRecursive(nums.sorted(), 0)
        return result
    }
    func subsetsRecursive(_ nums: [Int], _ start: Int) {
        result.append(set)
        if start >= nums.count { return }
        for i in start..<nums.count {
            if i > start, nums[i] == nums[i - 1] { continue }
            set.append(nums[i])
            subsetsRecursive(nums, i + 1)
            set.removeLast()
        }
    }
}
// @lc code=end