电子网站:datawhalechina.github.io/leetcode-no…
07.02
——————————
🚩—— day5
√ 112. 路径总和
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 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
C++ queue 【官方】
/**
* 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
/**
* 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 的更快
/**
* 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
# 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)
/**
* 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
⭐ 回溯
# 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
/**
* 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. 对称二叉树
递归
# 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)
# 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)
/**
* 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);
}
};
迭代 【层序遍历】
# 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
/**
* 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
/**
* 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
/**
* 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
/**
* 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)
# 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)
/**
* 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. 验证二叉搜索树
递归
# 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)
/**
* 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
/**
* 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
/**
* 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
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
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
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
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()
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
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
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
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
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
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)
/**
* 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
# 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
/**
* 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;
}
};