LeetCode 刷题集 - 散列表、二叉树、递归(2)

2021-04-01  本文已影响0人  Jacob6666

散列表(上):Word 文档中的单词拼写检查功能是如何实现的?

散列表(中):如何打造一个工业级水平的散列表?

散列表(下):为什么散列表和链表经常会一起使用?

哈希算法(上):如何防止数据库中的用户信息被脱库?

哈希算法(下):哈希算法在分布式系统中有哪些应用?

二叉树基础(上):什么样的二叉树适合用数组来存储?

二叉树基础(下):有了如此高效的散列表,为什么还需要二叉树?

递归树:如何借助树来求解递归算法的时间复杂度?

树的遍历 Demo

递归代码模板

如何优雅地计算斐波那契数列

LeetCode题目:

散列表

1.有效的字母异位词

class Solution {
//     // 排序然后对比解法
// func isAnagram(_ s: String, _ t: String) -> Bool {
//         let sortedS = s.sorted()
//         let sortedT = t.sorted()
//         return sortedS == sortedT ? true : false
//     }
// hashMap
    func isAnagram(_ s: String, _ t: String) -> Bool {
        if s.count != t.count { return false }
        var dictC = Dictionary<Character, Int>()
        var dictT = Dictionary<Character, Int>()
        for c in s {
            if let count = dictC[c] {
                dictC[c] = count + 1
            } else {
                dictC.updateValue(1, forKey: c)
            }
        }
        for c in t {
            if let count = dictT[c] {
                dictT[c] = count + 1
            } else {
                dictT.updateValue(1, forKey: c)
            }
        }
        for c in s {
            if dictC[c] != dictT[c] { return false }
        }
        return true
    }
}

2.字母异位词分组

class Solution {
    func groupAnagrams(_ strs: [String]) -> [[String]] {
        var res = Array<Array<String>>()
        var dict = Dictionary<Array<Int>, String>()
        for (index, str) in strs.enumerated() {
            let a: String = "a"
            let aNum = a.unicodeScalars.first!.value
            var key = Array(repeating: 0, count: 26)
            for c in str {
                key[Int(c.unicodeScalars.first!.value - aNum)] += 1
            }
            if dict[key] != nil {
                dict[key]! += "\(index),"
            } else {
                dict[key] = "\(index),"
            }
        }
        for (_, var value) in dict {
            value.removeLast()
            let indexArray = value.components(separatedBy: ",")
            var finalArray = Array<String>()
            for i in indexArray {
                finalArray.append(strs[Int(i)!])
            }
            res.append(finalArray)
        }
        return res
    }
}

二叉树

3.二叉树的前序遍历

class Solution {
        func preorderTraversal(_ root: TreeNode?) -> [Int] {
        var res = Array<Int>()
        preOrder(root, res: &res)
        return res
    }
    func preOrder(_ root: TreeNode?, res: inout Array<Int>) {
        // terminator
        if root == nil { return }
        // process current logic
        res.append(root!.val)
        // drill down
        preOrder(root?.left, res: &res)
        preOrder(root?.right, res: &res)
    }
}

4.N 叉树的前序遍历

class Solution {
        func preorder(_ root: Node?) -> [Int] {
            var res = Array<Int>()
            preorder(root, res: &res)
            return res
        }
        func preorder(_ root: Node?, res: inout Array<Int>) {
            if root == nil { return }
            res.append((root!.val))
            for i in 0..<(root?.children.count)! {
                preorder(root?.children[i], res: &res)
            }
        }
}

5.二叉树的中序遍历

class Solution {
     func inorderTraversal(_ root: TreeNode?) -> [Int] {
        var res = Array<Int>()
        inorder(root, res: &res)
        return res
    }
    func inorder(_ root: TreeNode?, res: inout Array<Int>) {
        if root == nil { return }
        inorder(root?.left, res: &res)
        res.append(root!.val)
        inorder(root?.right, res: &res)
    }
}

6.N 叉树的后序遍历

class Solution {
    func postorder(_ root: Node?) -> [Int] {
        var res = Array<Int>()
        postOrder(root, res: &res)
        return res
    }
    func postOrder(_ root: Node?, res: inout Array<Int>) {
        // terminator
        if root == nil { return }
        // process current logic
        for i in 0..<(root?.children.count)! {
            // drill down
            postOrder(root?.children[i], res: &res)
        }
        res.append(root!.val)
    }
}

7.N 叉树的层序遍历

class Solution {
    // 递归解法
    // func levelOrder(_ root: Node?) -> [[Int]] {
    //     var res = Array<Array<Int>>()
    //     var level = 0
    //     processOrder(root, res: &res, level: level)
    //     return res
    // }
    // func processOrder(_ root: Node?, res: inout Array<Array<Int>>, level: Int) {
    //     if root == nil { return }
    //     if res.count <= level {
    //         res.append([])
    //     }
    //     res[level].append(root!.val)
    //     let newLevel = level + 1
    //     for i in 0..<(root?.children.count)! {
    //         processOrder(root?.children[i], res: &res, level: newLevel)
    //     }
    // }
    //BFS解法
   func levelOrder(_ root: Node?) -> [[Int]] {
       guard let root = root else { return []}
       var queue = Array<Node?>()
       var res = Array<Array<Int>>()
        queue = [root]
       while !queue.isEmpty {
           let levelCount = queue.count
           var temp = Array<Int>()
           for _ in 0..<levelCount {
            let node = queue.removeFirst()
            temp.append(node!.val)
            node!.children.forEach { queue.append($0) }
           }
           res.append(temp)
       }
       return res
    }
}

8.翻转二叉树

class Solution {
    func invertTree(_ root: TreeNode?) -> TreeNode? {
        if root == nil { return nil}
        let left = invertTree(root?.left)
        let right = invertTree(root?.right)
        root?.left = right
        root?.right = left
        return root
    }
}

9.验证二叉搜索树

class Solution {
        func isValidBST(_ root: TreeNode?) -> Bool {
        var res = true
        var lower = Int64.min
        backTrack(root: root, lower: &lower, res: &res)
        return res
    }
    func backTrack(root: TreeNode?, lower: inout Int64, res: inout Bool) {
        // 左根右
        if root == nil {
            return }
        backTrack(root: root?.left, lower: &lower, res: &res)
        if lower >= root!.val {
            res = false
        }
        lower = Int64(root!.val)
        backTrack(root: root?.right, lower: &lower, res: &res)
    }

}

10.二叉树的最大深度

class Solution {
        func maxDepth(_ root: TreeNode?) -> Int {
        if root == nil { return 0 }
        let maxLeft = maxDepth(root?.left)
        let maxRight = maxDepth(root?.right)
        return max(maxLeft, maxRight) + 1
    }
}

11.二叉树的最小深度

class Solution {
    func minDepth(_ root: TreeNode?) -> Int {
        guard let root = root else {
            return 0
        }
        var minLevel = 0
        var queue = [root]
        while !queue.isEmpty {
            minLevel += 1
            for _ in 0..<queue.count {
                let currentNode = queue.removeFirst()
                if currentNode.left == nil && currentNode.right == nil {
                    return minLevel
                }
                if let right = currentNode.right {
                    queue.append(right)
                }
                if let left = currentNode.left {
                    queue.append(left)
                }
            }
        }
        return minLevel
    }
}

12.二叉树的序列化与反序列化

class Codec {
    func serialize(_ root: TreeNode?) -> String {
        guard let nonNilRoot = root else {
            return ""
        }
        return BFS(root: nonNilRoot)
    }
    func deserialize(_ data: String) -> TreeNode? {
        if data == "" {return nil}
        let NodeValueArray = data.split(separator: ",")
        // 构造一个TreeNode数组
        var treeNodeArray = Array<TreeNode?>()
        for i in NodeValueArray {
            if i == "Null" {
                treeNodeArray.append(nil)
            } else {
                treeNodeArray.append(TreeNode(Int(i)!))
            }
        }
        let resRoot:TreeNode? = treeNodeArray.first!
        var queue = Array<TreeNode?>()
        queue = [resRoot]
        var i = 1
        while !queue.isEmpty {
            if let currentRoot = queue.removeFirst() {
                if let left = treeNodeArray[i] {
                    currentRoot.left = left
                    queue.append(left)
                }
                if let right = treeNodeArray[i + 1] {
                    currentRoot.right = right
                    queue.append(right)
                }
                i += 2
            }
        }
        return resRoot
    }
    func BFS(root: TreeNode?) -> String {
        guard let root = root else {
            return ""
        }
        var queue: [TreeNode?] = [root]
        var res = "\(root.val),"
        while !queue.isEmpty {
            for _ in 0..<queue.count {
                let currentNode = queue.removeFirst()
                if let left = currentNode?.left {
                    queue.append(left)
                    res += "\(left.val),"
                } else {
                    res += "Null,"
                }
                if let right = currentNode?.right {
                    queue.append(right)
                    res += "\(right.val),"
                } else {
                    res += "Null,"
                }
                
            }
        }
        res.removeLast()
        return res
    }
}
// Your Codec object will be instantiated and called as such:
// var ser = Codec()
// var deser = Codec()
// deser.deserialize(ser.serialize(root))

13.二叉树的最近公共祖先

class Solution {
    func lowestCommonAncestor(_ root: TreeNode?, _ p: TreeNode?, _ q: TreeNode?) -> TreeNode?{
        if root == nil || root?.val == p?.val || root?.val == q?.val {
             return root
        }
        let left = lowestCommonAncestor(root?.left, p, q)
        let right = lowestCommonAncestor(root?.right, p, q)
        if left == nil  { return right }
        if right == nil { return left }
        return root
    }
}

14.从前序与中序遍历序列构造二叉树

class Solution {
func buildTree(_ preorder: [Int], _ inorder: [Int]) -> TreeNode? {
        var mPreorder = preorder
        var mInorder = inorder
        return backTrack(preorderNodeArray: &mPreorder, inorderNodeArray: &mInorder)
    }
    func backTrack(preorderNodeArray: inout [Int], inorderNodeArray: inout [Int]) -> TreeNode? {
        guard let rootVal = preorderNodeArray.first else {
            return nil
        }
        let root = TreeNode(rootVal)
        if preorderNodeArray.count == 1 {
            return root
        }
        var inorderLeftTree = Array(inorderNodeArray[0..<inorderNodeArray.firstIndex(of: root.val)!])
        var inorderRighTree = Array(inorderNodeArray[inorderNodeArray.firstIndex(of: root.val)! + 1..<inorderNodeArray.count])
        var preorderLeftTree = Array(preorderNodeArray[1..<inorderLeftTree.count + 1])
        var preorderRightTree = Array(preorderNodeArray[(inorderLeftTree.count + 1)..<preorderNodeArray.count])
        root.left = backTrack(preorderNodeArray: &preorderLeftTree, inorderNodeArray: &inorderLeftTree)
        root.right = backTrack(preorderNodeArray: &preorderRightTree, inorderNodeArray: &inorderRighTree)
        return root
    }
}

递归

9.括号生成

class Solution {
func generateParenthesis(_ n: Int) -> [String] {
        var res = Array<String>()
        backTrack(n: n, left: 0, right: 0, res: &res, cur: "")
        return res
    }
    func backTrack(n: Int, left: Int, right: Int, res: inout Array<String>, cur: String) {
        // terminator
        if cur.count == n * 2 {
            // process result
            res.append(cur)
            return
        }
        if left < n {
            backTrack(n: n, left: left + 1, right: right, res: &res, cur: cur + "(")
        }
        if right < left {
            backTrack(n: n, left: left, right: right + 1, res: &res, cur: cur + ")")
        }
    }
}

15.组合

class Solution {
    func combine(_ n: Int, _ k: Int) -> [[Int]] {
        var res = Array<Array<Int>>()
        var cur = Array<Int>()
        backTracking(n: n, k: k, res: &res, cur: &cur, curNum: 1)
        return res
    }
    func backTracking(n: Int, k: Int, res: inout Array<Array<Int>>, cur: inout Array<Int>, curNum: Int) {
        if cur.count + (n - curNum + 1) < k {
            return
        }
        if cur.count == k {
            res.append(cur)
            return
        }
        cur.append(curNum)
        backTracking(n: n, k: k, res: &res, cur: &cur, curNum: curNum + 1)
        cur.removeLast()
        backTracking(n: n, k: k, res: &res, cur: &cur, curNum: curNum + 1)
    }

}

16.全排列

class Solution {
func permute(_ nums: [Int]) -> [[Int]] {
        var path = Array<Int>()
        var res = Array<Array<Int>>()
        var used = Array(repeating: false, count: nums.count)
        dfs(path: &path, res: &res, used: &used, nums: nums, depth: 0)
        return res
    }
    func dfs(path: inout Array<Int>, res: inout Array<Array<Int>>, used: inout Array<Bool>, nums: Array<Int>, depth: Int) {
        if depth == nums.count {
            res.append(path)
            return
        }
        for i in 0..<nums.count {
            if used[i] { continue }
            path.append(nums[i])
            used[i] = true
            dfs(path: &path, res: &res, used: &used, nums: nums, depth: depth + 1)
            path.removeLast()
            used[i] = false
        }
    }
}

17.全排列 II

class Solution {
    func permuteUnique(_ nums: [Int]) -> [[Int]] {
        var res = Array<Array<Int>>()
        var path = Array<Int>()
        var used = Array(repeating: false, count: nums.count)
        dfs(nums: nums.sorted(by: <), res: &res, path: &path, level: 0, used: &used)
        return res
    }
    func dfs(nums: [Int], res: inout [[Int]], path: inout [Int], level: Int, used: inout [Bool]) {
        if level == nums.count {
            res.append(path)
            return
        }
        for i in 0..<nums.count {
            // !used[i - 1] 保证在填【i】这个数的时候重复数字只会被填入一次,只要最左边的。所以如果两个数字相同,并且前一个还没有用过,那么是不符合规则(用最左侧)的。要continue跳过
            if used[i] == true || (i > 0 && nums[i] == nums[i - 1] && !used[i - 1]) {
                continue
            }
            used[i] = true
            path.append(nums[i])
            dfs(nums: nums, res: &res, path: &path, level: level + 1, used: &used)
            path.removeLast()
            used[i] = false
        }
    }
}
上一篇下一篇

猜你喜欢

热点阅读