# 0318【LeetCode 算法笔记】Task02 63 - 74 【C++ 关于 网格四周搜索的写法】

110 阅读18分钟

开源内容:github.com/datawhalech…

电子网站:datawhalechina.github.io/leetcode-no…

07.02

对应题解 速查链接

——————————

🚩—— day5

112. 路径总和

BFS O(n)\lgroup O(n) \rgroup

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
        # BFS 
        if not root: # 由于 targetSum 必为 某个值,要是没节点,直接返回 False
            return False

        q = collections.deque([[root, root.val]]) # [结点, 当前和]  !!注意外面还有一个 括号! 
        # 普通的列表也可以,对顺序没要求
        while q:
            node, cur = q.popleft() # 
            if not node.left and not node.right and cur == targetSum: # 遇到 叶子结点, 判断
                return True 

            #  有负的, 不能因为 cur 大了, 就不添加了
            if node.left:
                q.append([node.left, cur + node.left.val])
            
            if node.right:
                q.append([node.right, cur + node.right.val])

        return False 

image.png

C++ queue 【官方】

queue 文档

image.png

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    bool hasPathSum(TreeNode* root, int targetSum) {
        if (!root){
            return false;  // 不要忘了!!
        }
        queue<pair<TreeNode*, int>> q; // 队列
        q.push({root, root->val});
        while (!q.empty()){
            TreeNode* node = q.front().first; // 
            int cur = q.front().second;
            q.pop();// queue     pop 的是 前面的 
            if (!node->left && !node->right && cur == targetSum){
                return true;
            }
            if (node->left){
                q.push({node->left, cur + node->left->val});
            }
            if (node->right){
                q.push({node->right, cur + node->right->val});
            }
        }
        return false;
    }
};

C++ stack

stack 文档

image.png

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    bool hasPathSum(TreeNode* root, int targetSum) {
        if (!root){
            return false;  // 不要忘了!!
        }
        stack<pair<TreeNode*, int>> q; // 顺序无所谓, 普通栈就可以
        q.push({root, root->val});
        while (!q.empty()){
            TreeNode* node = q.top().first; 
            int cur = q.top().second;
            q.pop();
            if (!node->left && !node->right && cur == targetSum){
                return true;
            }
            if (node->left){
                q.push({node->left, cur + node->left->val});
            }
            if (node->right){
                q.push({node->right, cur + node->right->val});
            }
        }
        return false;
    }
};

C++ vector 能用 emplace 或 emplace_back 的更快

vector 文档

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    bool hasPathSum(TreeNode* root, int targetSum) {
        if (!root){
            return false;  // 不要忘了!!
        }
        vector<pair<TreeNode*, int>> q; // 迭代器
        q.emplace_back(root, root->val);
        while (!q.empty()){
            TreeNode* node = q.back().first; // 由于 只能 pop_back ,因此,应看 最后一个
            int cur = q.back().second;
            q.pop_back();
            if (!node->left && !node->right && cur == targetSum){
                return true;
            }
            if (node->left){
                q.emplace_back(node->left, cur + node->left->val);
            }
            if (node->right){
                q.emplace_back(node->right, cur + node->right->val);
            }
        }
        return false;
    }
};

其它: array, list, queue等均可

DFS O(n)O(n)\lgroup O(n)、\leq O(n) \rgroup

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
        if not root:
            return False  

        if not root.left and not root.right and root.val == targetSum:
            return True 

        # if root.left:  No !!!
        #     return self.hasPathSum(root.left, targetSum - root.left.val)
        # if root.right:
        #     return self.hasPathSum(root.right, targetSum - root.right.val)

        # 可选 !!且减掉的是  前一个结点的值
        return self.hasPathSum(root.left, targetSum - root.val) or self.hasPathSum(root.right, targetSum - root.val)

image.png

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    bool hasPathSum(TreeNode* root, int targetSum) {
        if (root == nullptr){
            return false;
        }
        if (root->left == nullptr && root->right == nullptr && root->val == targetSum){
            return true;
        }
        return hasPathSum(root->left, targetSum - root->val) || hasPathSum(root->right, targetSum - root->val);
    }
};

113. 路径总和 II

⭐ 回溯 O(n2)O(n)\lgroup O(n^2)、O(n) \rgroup

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]:
        res = []
        path = []

        def backtrack(root, targetSum):
            if not root:
                return

            path.append(root.val)
            targetSum -= root.val 
            if not root.left and not root.right and targetSum == 0:
                res.append(path[:]) #  注意 这里

            backtrack(root.left, targetSum)
            backtrack(root.right, targetSum)
            path.pop()

        backtrack(root, targetSum)
        return res 

image.png

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
    vector<vector<int>> res;
    vector<int> path;

    void backtrack(TreeNode* root, int targetSum){
        if (!root){
            return;
        }
        path.emplace_back(root->val);
        targetSum -= root->val;
        if (!root->left && !root->right && targetSum == 0){
            res.emplace_back(path);
        }
        backtrack(root->left, targetSum);
        backtrack(root->right, targetSum);
        path.pop_back(); // 回溯
    }
public:
    vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
        backtrack(root, targetSum);
        return res;
    }
};

101. 对称二叉树

递归 O(n)\lgroup O(n) \rgroup

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def isSymmetric(self, root: Optional[TreeNode]) -> bool:
        # 注意 两边的树 是外侧和外侧等。 不是 左边的左子结点  和 右边的左子结点相等
        def dfs(p, q):
            if not p and not q:
                return True 
            if not p or not q or p.val != q.val:
                return False  

            return p.val == q.val and dfs(p.left, q.right) and dfs(p.right, q.left)

        return not root or dfs(root.left, root.right)

image.png

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def dfs(self, p, q):
        if not p and not q:
            return True 
        if not p or not q or p.val != q.val:
            return False  

        return p.val == q.val and self.dfs(p.left, q.right) and self.dfs(p.right, q.left)

    def isSymmetric(self, root: Optional[TreeNode]) -> bool:
        # 注意 两边的树 是外侧和外侧等。 不是 左边的左子结点  和 右边的左子结点相等
        return not root or self.dfs(root.left, root.right)

image.png

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    bool dfs(TreeNode* u, TreeNode* v){
        if (!u && !v){
            return true;
        }
        if (!u || !v || u->val != v->val){
            return false;
        }
        return u->val == v->val && dfs(u->left, v->right) && dfs(u->right, v->left);
    }
    bool isSymmetric(TreeNode* root) {
        return !root || dfs(root->left, root->right);
    }
};

迭代 【层序遍历】 O(n)\lgroup O(n) \rgroup

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def isSymmetric(self, root: Optional[TreeNode]) -> bool:
        if not root:
            return True 
        if not root.left and not root.right:
            return True 

        q = collections.deque([[root.left, root.right]])
        while q:
            u, v = q.popleft()
            if not u and not v: # 注意是继续 检查别的点,而不是 直接返回 True
                continue
            if not u or not v or u.val != v.val: # 只有 错的 可以直接返回
                return False 
            q.append([u.left, v.right]) # 
            q.append([u.right, v.left])

        return True

image.png

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        if (!root){
            return true;
        }
        if (!root->left && !root->right){
            return true;
        }

        queue<pair<TreeNode*, TreeNode*>> q;
        q.push({root->left, root->right});
        while (!q.empty()){
            TreeNode* u = q.front().first;
            TreeNode* v = q.front().second;
            q.pop();
            if (!u and !v){
                continue;
            }
            if (!u || !v || u->val != v->val){
                return false;
            }
            q.push({u->left, v->right});
            q.push({u->right, v->left});
        }
        return true;
    }
};

🚩—— day6

124. 二叉树中的最大路径和

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def __init__(self):
        self.maxSum = -inf
    
    def maxGain(self, node):
        if not node:
            return 0 

        leftGain = max(self.maxGain(node.left), 0)  # 大于0  才 取
        rightGain = max(self.maxGain(node.right), 0)

        self.maxSum = max(self.maxSum, node.val + leftGain + rightGain)
        # 返回 结点 最大的和
        return node.val + max(leftGain, rightGain)
        
    def maxPathSum(self, root: Optional[TreeNode]) -> int:
        self.maxGain(root)
        return self.maxSum

image.png

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
private:
    int maxSum = INT_MIN;

public:
    int maxGain(TreeNode* node){
        if (!node){
            return 0;
        }

        int leftGain = max(maxGain(node->left), 0);
        int rightGain = max(maxGain(node->right), 0);

        // 更新 最大值
        maxSum = max(maxSum, node->val + leftGain + rightGain);
        return node->val + max(leftGain, rightGain);// 二叉树, 只能 选 其中一侧
    }
    int maxPathSum(TreeNode* root) {
        maxGain(root);
        return maxSum;
    }
};

199. 二叉树的右视图

DFS

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def rightSideView(self, root: Optional[TreeNode]) -> List[int]:
        # 注意 左子树 比 右子树 深的情况 
        # 层序遍历, 弹出 最右边那个

        ret = []
        def dfs(cur, depth):
            if not cur:  return 
            if depth == len(ret): # 每层 取一个
                ret.append(cur.val)
            dfs(cur.right, depth + 1) # 先遍历的右边, 看到的第一个 就是
            dfs(cur.left, depth + 1)

        dfs(root, 0)
        return ret 

image.png

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    void dfs(TreeNode* cur, int depth, vector<int>& ret){
        if (!cur){
            return;
        }
        if (depth == ret.size()){
            ret.emplace_back(cur->val);
        }

        dfs(cur->right, depth + 1, ret);
        dfs(cur->left, depth + 1, ret);

    }
    vector<int> rightSideView(TreeNode* root) {
        // DFS 
        vector<int> ret;
        if (!root){
            return ret;
        }

        dfs(root, 0, ret);
        return ret;
    }
};

BFS

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def rightSideView(self, root: Optional[TreeNode]) -> List[int]:
        if not root:
            return []

        ret = []
        q = [root]
        while q:
            ret.append(q[-1].val)  # q 可 确保 非空
            nxt = []
            for node in q:
                if node.left:
                    nxt.append(node.left)
                if node.right:
                    nxt.append(node.right)
            q = nxt 

        return ret

image.png

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<int> rightSideView(TreeNode* root) {
        // BFS  O(N)、O(N)
        vector<int> ret;
        if (!root){
            return ret;
        }

        vector<TreeNode*> q;
        q.emplace_back(root);
        while (!q.empty()){
            ret.emplace_back(q.back()->val);
            vector<TreeNode*> nxt;
            for (TreeNode* cur : q){// queue 不能这样遍历
                if (cur->left){
                    nxt.emplace_back(cur->left);
                }
                if (cur->right){
                    nxt.emplace_back(cur->right);
                }
            }

            q = move(nxt);
        }
        return ret;
    }
};

226. 翻转二叉树

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        if not root:
            return root 

        root.left, root.right = self.invertTree(root.right), self.invertTree(root.left)

        return root 
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        if not root:
            return 

        stack = [root]
        while stack:
            node = stack.pop()
            if node.left: stack.append(node.left)
            if node.right: stack.append(node.right)
            node.left, node.right = node.right, node.left
        return root
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        if (!root){
            return root;
        }

        TreeNode* tmp = root->left;  // 注意 是交换
        root->left = invertTree(root->right);
        root->right = invertTree(tmp);

        return root;

    }
};

🚩—— day7

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

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
    # 前序 根 左 右    第一个 根节点   在 中序 查找 根的位置  左右树 切分  继续递归
    # 中序 左 根 右   

    ## 
        if not preorder: 
            return None 
        idx = inorder.index(preorder[0])   # 中序中 左右子树的分割点 根的索引  同时也是 左子树的节点数
        left = self.buildTree(preorder[1 : 1 + idx], inorder[: idx])
        right = self.buildTree(preorder[1 + idx : ], inorder[idx + 1: ])
        return TreeNode(preorder[0], left, right)

image.png

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
      # 前序 根 左 右    第一个 根节点   在 中序 查找 根的位置  左右树 切分  继续递归
        # 中序 左 根 右  
        def dfs(pre_left, pre_right, in_left, in_right):# 处理的 preorder 的 元素索引范围,inorder 的元素索引范围
            if pre_left > pre_right:
                return None 

            # 分 左右子树
            idx = dic[preorder[pre_left]]  # 获取 中序中 根的 位置索引  # 
            left_size = idx - in_left  # 左子树 节点数  # 0  1 2 3 

            # 建根
            root = TreeNode(preorder[pre_left])
            root.left = dfs(pre_left + 1, pre_left + left_size, in_left, idx - 1)
            root.right = dfs(pre_left + left_size + 1, pre_right, idx + 1, in_right)
            return root 

        n = len(preorder)
        dic = {element : i for i, element in enumerate(inorder)} # 结点值 : 索引 
        return dfs(0, n - 1, 0, n - 1)

image.png

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
private:
    unordered_map<int, int> dic;
public:
    //  递归 构造模块
    TreeNode* myBuildTree(const vector<int>& preorder, const vector<int>& inorder, int pre_left, int pre_right, int in_left, int in_right){
        
        if (pre_left > pre_right){
            return nullptr;
        }
        
        int idx = dic[preorder[pre_left]];  // 本次循环 建树的根节点 在 inorder 的位置
        int left_size = idx - in_left;  // 左子树的节点个数

        // 建 根节点
        TreeNode* root = new TreeNode(preorder[pre_left]);
        root->left = myBuildTree(preorder, inorder, pre_left + 1, pre_left + left_size, in_left, idx - 1);
        root->right = myBuildTree(preorder, inorder, pre_left + left_size + 1, pre_right, idx + 1, in_right);

        return root;
    }
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        // 构造 哈希映射 快速定位 inorder 中的根节点
        int n = preorder.size();
        for (int i = 0; i < n; ++i){
            dic[inorder[i]] = i;   // 节点值 : inorder 中的索引
        }
        return myBuildTree(preorder, inorder, 0, n - 1, 0, n - 1); // 要处理的 preorder 中的 节点索引范围, inorder 中的节点 索引范围
    }
};

98. 验证二叉搜索树

image.png

image.png

递归

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def isValidBST(self, root: Optional[TreeNode]) -> bool:
        # 二叉搜索树: 左 < 根 < 右
        def dfs(root, left0, right0):  # 根结点, 以及 要满足的下界 和 上界
            if not root:
                return True 

            return left0 < root.val < right0 and dfs(root.left, left0, root.val) and dfs(root.right, root.val, right0)

        return dfs(root, -inf, inf)

image.png

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    bool dfs(TreeNode* root, long long left0, long long right0){
        if (!root){
            return true;
        }
        long long x = root->val;
        return left0 < x && x < right0 && dfs(root->left, left0, x) and dfs(root->right, x, right0);
    }
    bool isValidBST(TreeNode* root) {
        return dfs(root, LONG_MIN, LONG_MAX);
    }
};

中序遍历 左根右

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def isValidBST(self, root: Optional[TreeNode]) -> bool:
        # 中序遍历  二叉搜索树 必定是 升序的
        stack = []
        inorder = -inf  # 记录前一个值

        while stack or root: # 左 根 右
            while root:
                stack.append(root)
                root = root.left 
            root = stack.pop() 
            if root.val <= inorder:
                return False 
            inorder = root.val 
            root = root.right
            
        return True

image.png

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    bool isValidBST(TreeNode* root) {
        long long inorder = LONG_MIN;
        stack<TreeNode*> stk;
        while (!stk.empty() || root){
            while (root){
                stk.push(root);
                root = root->left;
            }

            root = stk.top(); stk.pop();
            if (root->val <= inorder){
                return false;
            }
            inorder = root->val;
            root = root->right;
        }
        return true;
    }
};

110. 平衡二叉树 【递归】

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def isBalanced(self, root: Optional[TreeNode]) -> bool:
        # 平衡 二叉树, 左右子树深度差 不超过 1

        # 树 的深度 = max (左子树深度, 右子树深度) + 1

        def dfs(root):  # 递归:  不是非平衡子树, 就返回 深度, 便于下一轮计算
            if not root:
                return 0 

            left = dfs(root.left)  # 左子树深度差 或 -1
            right = dfs(root.right)
            if left == -1 or right == -1 or abs(left - right) > 1:  # 非平衡树
                return -1 
            return max(left, right) + 1

        
        return dfs(root) != -1

image.png

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    int dfs(TreeNode* root){
        if (!root){
            return 0;
        }
        int left = dfs(root->left);
        int right = dfs(root->right);
        if (left == -1 || right == -1 || abs(right - left) > 1){
            return -1; // 非平衡树
        }
        return max(left, right) + 1;
    }
    bool isBalanced(TreeNode* root) {
        return dfs(root) != -1;     
    }
};

🚩—— day8

200. 岛屿数量

DFS O(mn)O(mn)

class Solution:
    def numIslands(self, grid: List[List[str]]) -> int:
        # 找到一个岛屿后, 把其它 连接的区域都上色

        def dfs(i, j):
            grid[i][j] = '#'
            for nx, ny in (i + 1, j), (i - 1, j), (i, j + 1), (i, j - 1):
                if 0 <= nx < m and 0 <= ny < n and grid[nx][ny] == "1":  # 注意是 字符!!
                    dfs(nx, ny)

        ret = 0
        m, n = len(grid), len(grid[0])
        for i in range(m):
            for j in range(n):
                if grid[i][j] == "1":
                    ret += 1
                    dfs(i, j)  #同一个岛的 标记
        return ret 

image.png

class Solution {
private:
    void dfs(vector<vector<char>>& grid, int i, int j){
        grid[i][j] = '#';
        int di[4] = {1, -1, 0, 0};
        int dj[4] = {0, 0, 1, -1};
        for (int idx = 0; idx < 4; ++idx){
            int ni = i + di[idx], nj = j + dj[idx];
            if (ni >= 0 && ni < grid.size() && nj >= 0 && nj < grid[0].size() && grid[ni][nj] == '1'){
                dfs(grid, ni, nj);
            }
        }
    }

public:
    int numIslands(vector<vector<char>>& grid) {
        int ret = 0; // 岛屿 数量
        for (int i = 0; i < grid.size(); ++i){
            for (int j = 0; j < grid[0].size(); ++j){
                if (grid[i][j] == '1'){
                    ++ret;
                    dfs(grid, i, j);                    
                }
            }
        }
        return ret;
    }
};

BFS O(mn)O(mn)

class Solution:
    def numIslands(self, grid: List[List[str]]) -> int:
        ret = 0
        m, n = len(grid), len(grid[0])
        for i in range(m):
            for j in range(n):
                if grid[i][j] == "1":
                    ret += 1
                    grid[i][j] = '#'
                    # 给 同一岛屿的其它 "1" 区域 都做上标记
                    q = collections.deque([(i, j)])
                    while q:
                        x, y = q.popleft()
                        for nx, ny in (x + 1, y), (x - 1, y), (x, y -1), (x, y + 1):
                            if 0 <= nx < m and 0 <= ny < n and grid[nx][ny] == "1":
                                grid[nx][ny] = '#'
                                q.append((nx, ny))
        return ret 

image.png

class Solution {
public:
    int numIslands(vector<vector<char>>& grid) {
        int ret = 0; // 岛屿数量
        int m = grid.size(), n = grid[0].size();
        for (int i = 0; i < m; ++i){
            for (int j = 0; j < n; ++j){
                if (grid[i][j] == '1'){
                    grid[i][j] = '#';
                    ++ret;
                    queue<pair<int, int>> q;
                    q.push({i, j});
                    while (!q.empty()){
                        int x = q.front().first, y = q.front().second;
                        q.pop();
                        int dx[4] = {1, -1, 0, 0};
                        int dy[4] = {0, 0, 1, -1};
                        for (int idx = 0; idx < 4; ++idx){
                            int nx = x + dx[idx], ny = y + dy[idx];
                            if (nx >= 0 && nx < m && ny >= 0 && ny < n && grid[nx][ny] == '1'){
                                grid[nx][ny] = '#';
                                q.push({nx, ny});
                            }
                        }
                    }
                }
            }
        }
        return ret;        
    }
};

并查集 【并查集 按秩合并,不会重复查找,无需标记】

class UnionFind:
    def __init__(self, grid):
        m, n = len(grid), len(grid[0])
        self.parent = [-1] * (m * n)
        self.rank = [0] * (m * n)  # 每个区域 包含的 1 结点数目
        self.cnt =  0  # 连通分量 的数目
        for i in range(m):
            for j in range(n):
                if grid[i][j] == "1":
                    self.parent[i * n + j] = i * n + j 
                    self.cnt += 1  # grid 中所有 1 的个数
                    self.rank[i * n + j] = 1

    def find(self, i): # 
        if self.parent[i] != i:
            self.parent[i] = self.find(self.parent[i])
        return self.parent[i]

    def union(self, x, y):
        rootx = self.find(x)
        rooty = self.find(y)
        if rootx != rooty:
            if self.rank[rootx] < self.rank[rooty]:
                rootx, rooty = rooty, rootx 
            self.parent[rooty] = rootx  # 小的 指向 大的
            self.rank[rootx] += self.rank[rooty]  # 大的越大
            self.cnt -= 1    # 合并了, 少了一个 连通分量

    def getCount(self):  # 返回 无法 合并的 区域个数
        return self.cnt 


class Solution:
    def numIslands(self, grid: List[List[str]]) -> int:
        m, n = len(grid), len(grid[0])
        uf = UnionFind(grid)
        for i in range(m):
            for j in range(n):
                if grid[i][j] == "1":
                    for nx, ny in (i - 1, j), (i + 1, j), (i, j + 1), (i, j - 1):
                        if 0 <= nx < m and 0 <= ny < n and grid[nx][ny] == "1":
                            uf.union(i * n + j, nx * n + ny)

        return uf.getCount()

image.png

class UnionFind{
public:
    UnionFind(vector<vector<char>>& grid){
        cnt = 0;
        for (int i = 0; i < grid.size(); ++i){
            for (int j = 0; j < grid[0].size(); ++j){
                if (grid[i][j] == '1'){
                    parent.emplace_back(i * grid[0].size() + j);
                    ++cnt;
                }else{
                    parent.emplace_back(-1);
                }
                rank.emplace_back(0);
            }
        }
    }

    int find(int i){
        if (parent[i] != i){// 不指向自己, 说明 指向更高秩的
            parent[i] = find(parent[i]);
        }
        return parent[i];
    }

    void unite(int x, int y){
        int rootx = find(x), rooty = find(y);
        if (rootx != rooty){
            if (rank[rootx] < rank[rooty]){
                swap(rootx, rooty);
            }
            parent[rooty] = rootx;
            rank[rootx] += rank[rooty];
            --cnt;            
        }
    }

    int getCount() const{
        return cnt;
    }

private:
    vector<int> parent;
    vector<int> rank;
    int cnt; // 剩余 的未联通区域
};

class Solution {
public:
    int numIslands(vector<vector<char>>& grid) {
        int m = grid.size(), n = grid[0].size();
        UnionFind uf(grid);
        for (int i = 0; i < m; ++i){
            for (int j = 0; j < n; ++j){
                if (grid[i][j] == '1'){
                    int di[4] = {1, -1, 0, 0};
                    int dj[4] = {0, 0, 1, -1};
                    for (int idx = 0; idx < 4; ++idx){
                        int ni = i + di[idx], nj = j + dj[idx];
                        if (ni >= 0 && ni < m && nj >= 0 && nj < n && grid[ni][nj] == '1'){
                            uf.unite(i * n + j, ni * n + nj);
                        }
                    }
                }
            }
        }
        return uf.getCount();        
    }
};

695. 岛屿的最大面积

DFS O(mn)O(mn)

class Solution:
    def maxAreaOfIsland(self, grid: List[List[int]]) -> int:
        # DFS 
        def dfs(i, j):  # 返回 面积
            grid[i][j] = '#'
            s = 1
            for nx, ny in (i + 1, j), (i - 1, j), (i, j - 1), (i, j + 1):
                if 0 <= nx < m  and 0 <= ny < n and grid[nx][ny] == 1:
                    s += dfs(nx, ny)
            return s  # 四周 都没有 1 了,返回 s
        
        maxS = 0
        m, n = len(grid), len(grid[0])
        for i in range(m):
            for j in range(n):
                if grid[i][j] == 1:
                    ret = dfs(i, j)
                    if ret > maxS:
                        maxS = ret

        return maxS

image.png

class Solution:
        # DFS 
    def dfs(self, grid, i, j):  # 返回 面积
        grid[i][j] = '#'
        s = 1
        for nx, ny in (i + 1, j), (i - 1, j), (i, j - 1), (i, j + 1):
            if 0 <= nx < len(grid)  and 0 <= ny < len(grid[0]) and grid[nx][ny] == 1:
                s += self.dfs(grid, nx, ny)
        return s

    def maxAreaOfIsland(self, grid: List[List[int]]) -> int:
        maxS = 0
        m, n = len(grid), len(grid[0])
        for i in range(m):
            for j in range(n):
                if grid[i][j] == 1:
                    ret = self.dfs(grid, i, j)
                    if ret > maxS:
                        maxS = ret

        return maxS       

image.png

class Solution {
    int dfs(vector<vector<int>>& grid, int i, int j){
        if (i < 0 || j < 0 || i == grid.size() || j == grid[0].size() || grid[i][j] != 1){
            return 0;
        }
        grid[i][j] = '#';// 这个 没影响
        int di[4] = {0, 0, 1, -1};
        int dj[4] = {1, -1, 0, 0};
        int ret = 1;  // 岛屿的面积
        for (int idx = 0; idx < 4; ++idx){
            int ni = i + di[idx], nj = j + dj[idx];
            ret += dfs(grid, ni, nj);
        }
        return ret;
    }
public:
    int maxAreaOfIsland(vector<vector<int>>& grid) {
        int s = 0;
        for (int i = 0; i < grid.size(); ++i){
            for (int j = 0; j < grid[0].size(); ++j){
                s =max(s, dfs(grid, i, j));
            }
        }
        return s;
    }
};

BFS O(mn)O(mn)

class Solution:
    def maxAreaOfIsland(self, grid: List[List[int]]) -> int:
        # BFS 
        maxS = 0
        m, n = len(grid), len(grid[0])
        for i in range(m):
            for j in range(n):
                if grid[i][j] == 1:
                    grid[i][j] = '#'
                    s = 1
                    q = collections.deque([(i, j)])
                    while q:
                        x, y = q.popleft()
                        for nx, ny in (x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1):
                            if 0 <= nx < m and 0 <= ny < n and grid[nx][ny] == 1:
                                grid[nx][ny] = '#'
                                s += 1
                                q.append((nx, ny))

                    if s > maxS:
                        maxS = s

        return maxS

image.png

class Solution {
public:
    int maxAreaOfIsland(vector<vector<int>>& grid) {
        int maxS = 0;  // 最大的岛屿的面积
        int m = grid.size(), n = grid[0].size();
        for (int i = 0; i < m; ++i){
            for (int j = 0; j < n; ++j){
                if (grid[i][j] == 1){
                    grid[i][j] = '#';
                    int s = 1; // 岛屿面积
                    queue<pair<int, int>> q;
                    q.push({i, j});
                    while (!q.empty()){
                        int x = q.front().first, y = q.front().second;
                        q.pop();
                        int dx[4] = {0, 0, 1, -1};
                        int dy[4] = {1, -1, 0, 0};
                        for (int idx = 0; idx < 4; ++idx){
                            int nx = x + dx[idx], ny = y + dy[idx];
                            if (nx >= 0 && nx < m && ny >= 0 && ny < n && grid[nx][ny] == 1){
                                grid[nx][ny] = '#';
                                s += 1;
                                q.push({nx, ny});
                            }
                        }                       
                    if (s > maxS){
                        maxS =s;
                    }
                    }                    
                }

            }
        }
        return maxS;
    }
};

并查集

# 并查集
class UnionFind:
    def __init__(self, grid):
        m, n = len(grid), len(grid[0])
        self.parent = [-1] * (m * n)  # 
        self.rank = [0] * (m * n)
        for i in range(m):
            for j in range(n):
                if grid[i][j] == 1:
                    self.parent[i * n + j] = i * n + j  # 指向自己
                    self.rank[i * n + j] = 1   # 不断 合并 到 大的

    def find(self, i):
        if self.parent[i] != i:
            self.parent[i] = self.find(self.parent[i])
        return self.parent[i]

    def union(self, x, y):
        rootx, rooty = self.find(x), self.find(y)
        if rootx != rooty:
            if self.rank[rootx] < self.rank[rooty]:  # rootx 最大
                rootx, rooty = rooty, rootx 
            self.parent[rooty] = rootx # rooty  -> rootx(大)
            self.rank[rootx] += self.rank[rooty] # 大的更大  

class Solution:
    def maxAreaOfIsland(self, grid: List[List[int]]) -> int:
        m, n = len(grid), len(grid[0])
        uf = UnionFind(grid)
        for i in range(m):
            for j in range(n):
                if grid[i][j] == 1:
                    for x, y in [(i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1)]:
                        if 0 <= x < m and 0 <= y < n and grid[x][y] == 1:
                            uf.union(i * n + j, x * n + y)
        return max(uf.rank)

class UnionFind{
public:
    vector<int> rank;
    UnionFind(vector<vector<int>>& grid){
        int m = grid.size(), n = grid[0].size();
        for (int i = 0; i < m; ++i){
            for (int j = 0; j < n; ++j){
                if (grid[i][j] == 1){
                    parent.emplace_back(i * n + j);
                    rank.emplace_back(1);
                }else{
                    parent.emplace_back(-1);
                    rank.emplace_back(0);
                }
            }
        }
    }

    int find(int i){
        if (parent[i] != i){
            parent[i] = find(parent[i]);
        }
        return parent[i];
    }

    void unite(int x, int y){
        int rootx = find(x);
        int rooty = find(y);
        if (rootx != rooty){
            if (rank[rootx] < rank[rooty]){
                swap(rootx, rooty);
            }
            parent[rooty] = rootx;
            rank[rootx] += rank[rooty];
        }
    }
private:
    vector<int> parent;
    // vector<int> rank;
};


class Solution {
public:
    int maxAreaOfIsland(vector<vector<int>>& grid) {
        int m = grid.size(), n = grid[0].size();

        UnionFind uf(grid);
        for (int i = 0; i < m; ++i){
            for (int j = 0;j < n; ++j){
                if (grid[i][j] == 1){
                    int di[4] = {1, -1, 0, 0};
                    int dj[4] = {0, 0, 1, -1};
                    for (int idx = 0; idx < 4; ++idx){
                        int ni = i + di[idx], nj = j + dj[idx];
                        if (ni >= 0 && ni < m && nj >= 0 && nj < n && grid[ni][nj] == 1){
                            uf.unite(i * n + j, ni * n + nj);
                        }
                    }
                }
            }
        }
        return *max_element(uf.rank.begin(), uf.rank.end());
    }
};

129. 求根节点到叶节点数字之和

DFS

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def sumNumbers(self, root: Optional[TreeNode]) -> int:

        def dfs(root, preSum):
            if not root:
                return 0

            total = preSum * 10 + root.val
            if not root.left and not root.right:
                return total  ## 已经 处理完 返回 结果
                
            return dfs(root.left, total) + dfs(root.right, total)  # 所有数字 加到 一起
                    
        return dfs(root, 0)

image.png

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    int dfs(TreeNode* root, int preSum){// 因为 递归的时候 没做判断, 使用左右结点->val 会报错, 所以 先经 循环
        if (!root){
            return 0;
        }

        int total = preSum * 10 + root->val;
        if (!root->left && !root->right){
            return total;
        }
        return dfs(root->left, total) + dfs(root->right, total);
    }
    int sumNumbers(TreeNode* root) {
        return dfs(root, 0);
    }
};

BFS

image.png

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def sumNumbers(self, root: Optional[TreeNode]) -> int:
        if not root:
            return 0 

        total = 0 
        q = collections.deque([[root, root.val]])
        while q:
            node, curSum = q.popleft()
            if not node.left and not node.right:
                total += curSum 

            if node.left:
                q.append([node.left, curSum * 10 + node.left.val])
            if node.right:
                q.append([node.right, curSum * 10 + node.right.val])

        return total 

image.png

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    int sumNumbers(TreeNode* root) {
        if (!root){
            return 0;
        }
        
        int total = 0;
        queue<pair<TreeNode*, int>> q;
        q.push({root, root->val});
        while (!q.empty()){
            TreeNode* node = q.front().first;
            int curSum = q.front().second;
            q.pop();
            if (!node->left && !node->right){
                total += curSum;
            }
            if (node->left){
                q.push({node->left, curSum * 10 + node->left->val});
            }
            if (node->right){
                q.push({node->right, curSum * 10 + node->right->val});
            }
        }
        return total;
    }
};