宫水三叶
230. 二叉搜索树中第K小的元素 - 力扣(LeetCode)
二叉搜索树的中序遍历是有序的,因此我们只需要对二叉搜索树执行中序遍历,并返回第 k 小的值即可。
class Solution {
public:
int ans = -1;
int cnt = 0;
int kthSmallest(TreeNode* root, int k) {
//中序遍历
dfs(root, k);
return ans;
}
void dfs(TreeNode* root, int k)
{
if(ans != -1) return ;//找到答案。
if(root == nullptr) return ;
dfs(root->left, k);
cnt += 1;
if(cnt == k) ans = root->val;//这说正好是根为第k小
dfs(root->right, k);
}
};
240. 搜索二维矩阵 II - 力扣(LeetCode)
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
int n = matrix.size(), m = matrix[0].size();
int x = 0, y = m - 1;
while(x < n && y >= 0)
{
if(target == matrix[x][y]) return true;
else if(target > matrix[x][y]) x ++;
else y --;
}
return false;
}
};
297. 二叉树的序列化与反序列化 题解 - 力扣(LeetCode)
istringstream、ostringstream、stringstream 类介绍
层序遍历
class Codec {
public:
// Encodes a tree to a single string.
string serialize(TreeNode* root) {
ostringstream out;
queue<TreeNode*> q;
q.push(root);
while(!q.empty())//层序遍历
{
TreeNode* tmp = q.front();
q.pop();
if(tmp)
{
out << tmp->val << " ";
q.push(tmp->left);
q.push(tmp->right);
}
else out << "null ";
}
return out.str();
}
// Decodes your encoded data to tree.
TreeNode* deserialize(string data) {
istringstream input(data);
string val;
vector<TreeNode*> vec;
while(input >> val)
{
if(val == "null")
vec.push_back(NULL);
else
vec.push_back(new TreeNode(stoi(val)));
}
int j = 1;//j是儿子i是父亲
for(int i = 0; i < vec.size(); i ++ )
{
if(vec[i] == NULL) continue;
if(j < vec.size()) vec[i]->left = vec[j ++];
if(j < vec.size()) vec[i]->right = vec[j ++];
}
return vec[0];
}
};
前序遍历
class Codec {
public:
ostringstream out;
istringstream input;
// Encodes a tree to a single string.
string serialize(TreeNode* root) {
dfs1(root);
cout << out.str() << endl;
return out.str();
}
// Decodes your encoded data to tree.
TreeNode* deserialize(string data) {
cout << data;
input.str(data);//输入到input中
string sroot;
input >> sroot;
if(sroot == "NULL") return nullptr;
TreeNode* root = new TreeNode(stoi(sroot));
dfs2(root);
return root;
}
void dfs1(TreeNode* root)
{
//前序遍历
if(root == nullptr)
{
out << "NULL ";
return;
}
out << to_string(root->val) << " ";
dfs1(root->left);
dfs1(root->right);
}
void dfs2(TreeNode* root)
{
if(root == nullptr) return;
string l, r;
//有了根节点,先找左树再找右数
input >> l;
if(l != "NULL") root->left = new TreeNode(stoi(l));
dfs2(root->left);
input >> r;
if(r != "NULL") root->right = new TreeNode(stoi(r));
dfs2(root->right);
}
};
437. 路径总和 III - 力扣(LeetCode)
class Solution {
public:
int ans = 0;
int pathSum(TreeNode* root, int targetSum) {
dfs1(root, targetSum);
return ans;
}
int dfs2(TreeNode* root, int sum)//以root为根节点的和为sum的路径数量
{
if(root == nullptr) return 0;
int res = 0;
if(root->val == sum) res ++;//可能还可以往下走
res += dfs2(root->right, sum - root->val);
res += dfs2(root->left, sum - root->val);
return res;
}
void dfs1(TreeNode* root, int sum)
{
if(root == nullptr) return ;
ans += dfs2(root, sum);
dfs1(root->right, sum);
dfs1(root->left, sum);
}
};
class Solution {
public:
unordered_map<long long, int> prefix;
int dfs(TreeNode *root, long long curr, int targetSum) {
if (!root) {
return 0;
}
int ret = 0;
curr += root->val;
if (prefix.count(curr - targetSum)) {
ret = prefix[curr - targetSum];
}
prefix[curr]++;
ret += dfs(root->left, curr, targetSum);
ret += dfs(root->right, curr, targetSum);
prefix[curr]--;
return ret;
}
int pathSum(TreeNode* root, int targetSum) {
prefix[0] = 1;
return dfs(root, 0, targetSum);
}
};
563. 二叉树的坡度 - 力扣(LeetCode)
class Solution {
public:
int ans = 0;
int findTilt(TreeNode* root) {
dfs(root);
return ans;
}
int dfs(TreeNode* root)
{
if(root == nullptr) return 0;
int ls = dfs(root->right);
int rs = dfs(root->left);
ans += abs(ls - rs);
return ls + rs + root->val;
}
};
class Solution {
public:
int findTilt(TreeNode* root) {
if(root == nullptr) return 0;
return findTilt(root->left) + findTilt(root->right) + abs(get(root->right) - get(root->left));
}
int get(TreeNode* root)
{
if(root == nullptr) return 0;
return get(root->left) + get(root->right) + root->val;
}
};
783. 二叉搜索树节点最小距离 - 力扣(LeetCode)
class Solution {
public:
int ans = 1e9;
int minDiffInBST(TreeNode* root) {
int a = -1, b = 1e9;
dfs(root, a, b);
return ans;
}
void dfs(TreeNode* root, int &a, int &b)//最大、最小
{
if(root == nullptr) return;
int m1 = -1, m2 = 1e9, m3 = -1, m4 = 1e9;
dfs(root->left, m1, m2);
dfs(root->right, m3, m4);
if(m1 != -1) ans = min(ans, abs(root->val - m1));
if(m4 != 1e9) ans = min(ans, abs(root->val - m4));
a = max({a, m1, m3, root->val});
b = min({b, m2, m4, root->val});
}
};
中序遍历
class Solution {
public:
int last = -1;
int ans = 1e9;
int minDiffInBST(TreeNode* root) {
dfs(root);
return ans;
}
void dfs(TreeNode* root)
{
if(root == nullptr) return;
dfs(root->left);
if(last >= 0) ans = min(ans, abs(last - root->val));
last = root->val;
dfs(root->right);
}
};
863. 二叉树中所有距离为 K 的结点 - 力扣(LeetCode)
class Solution {
public:
vector<int> ret;
unordered_map<TreeNode*, TreeNode*> mp;
unordered_set<TreeNode*> se;
vector<int> distanceK(TreeNode* root, TreeNode* target, int k) {
dfs(root);//找到父亲节点
calc(target, k);//从target开始找
return ret;
}
void calc(TreeNode* t, int k)
{
if(!t || se.count(t)) return;//寻找过了
se.insert(t);
if(!k)
{
ret.push_back(t->val);
return;
}
calc(t->left, k - 1);
calc(t->right, k - 1);
calc(mp[t], k - 1);
}
void dfs(TreeNode* t)
{
if(!t) return;
if(t->left) mp[t->left] = t, dfs(t->left);
if(t->right) mp[t->right] = t, dfs(t->right);
}
};
938. 二叉搜索树的范围和 - 力扣(LeetCode)
class Solution {
public:
int rangeSumBST(TreeNode* root, int low, int high) {
if(root == nullptr) return 0;
if(root->val < low || root->val > high) root->val = 0;
return rangeSumBST(root->right, low, high) + rangeSumBST(root->left, low, high) + root->val;
}
};
987. 二叉树的垂序遍历 - 力扣(LeetCode)
class Solution {
public:
unordered_map<int, unordered_map<int,int>> mp;
struct point
{
int x, y;
vector<int> g;
bool operator < (const point &rhs) const
{
if(y == rhs.y)
return x < rhs.x;
return y < rhs.y;
}
}e[2000];
int cnt = 0;
int m1 = 0;
int m2 = 0;
vector<vector<int>> verticalTraversal(TreeNode* root) {
e[cnt ++ ] = {0, 0, {root->val}};
mp[0][0] = cnt - 1;
dfs(root->right, 1, 1);
dfs(root->left, 1, -1);
sort(e, e + cnt);
vector<vector<int>> ans(m2 - m1 + 1);
for(int i = 0; i < cnt; i ++ )
{
if(e[i].g.size() > 1) sort(e[i].g.begin(), e[i].g.end());
int index = e[i].y;//列
for(int j = 0; j < e[i].g.size(); j ++ )
{
ans[index - m1].push_back(e[i].g[j]);
}
}
return ans;
}
void dfs(TreeNode* root, int x, int y)
{
if(root == nullptr) return;
if(!mp[x][y])
{
e[cnt].x = x, e[cnt].y = y;
e[cnt].g.push_back(root->val);
mp[x][y] = cnt;
cnt ++;
}
else e[mp[x][y]].g.push_back(root->val);
m2 = max(m2, y);//最大
m1 = min(m1, y);//最小
dfs(root->right, x + 1, y + 1);
dfs(root->left, x + 1, y - 1);
}
};
在这里插入代码片
993. 二叉树的堂兄弟节点 - 力扣(LeetCode)
class Solution {
public:
int dx, dy, fx, fy;
bool isCousins(TreeNode* root, int x, int y) {
dfs(root, x, y, 0, root->val);
return dx == dy && fx != fy;
}
void dfs(TreeNode* root, int x, int y, int dep, int fa)
{
if(root == nullptr) return;
dfs(root->right, x, y, dep + 1, root->val);
dfs(root->left, x, y, dep + 1, root->val);
if(root->val == x) dx = dep, fx = fa;
if(root->val == y) dy = dep, fy = fa;
}
};
class Solution {
public:
int dep[200];//200层的数量
vector<int> ans;
vector<int> pathInZigZagTree(int label) {
//首先判断是哪一行
int sum = 0;
int p;
for(int i = 1; i <= label; i ++ )
{
sum += pow(2, i - 1);
dep[i] = sum;
if(sum >= label)
{
p = i;
break;
}
}
dfs(label, p);
reverse(ans.begin(), ans.end());
return ans;
}
void dfs(int x, int p)
{
ans.push_back(x);
if(x == 1)
return;
int y;//经典值
if(p % 2 == 0) //偶数行,从右往左
{
y = dep[p] - x + 1 + dep[p - 1];
dfs(y / 2, p - 1);//上一行的真实值
}
else
{
y = x;
dfs(dep[p - 1] + (dep[p - 1] + 1)/ 2 - y / 2, p - 1);
}
}
};
1104. 二叉树寻路 - 力扣(LeetCode)
class Solution {
public:
int dep[200];//200层的数量
vector<int> ans;
vector<int> pathInZigZagTree(int label) {
//首先判断是哪一行
int sum = 0;
int p;
for(int i = 1; i <= label; i ++ )
{
sum += pow(2, i - 1);
dep[i] = sum;
if(sum >= label)
{
p = i;
break;
}
}
dfs(label, p);
reverse(ans.begin(), ans.end());
return ans;
}
void dfs(int x, int p)
{
ans.push_back(x);
if(x == 1)
return;
int y;
if(p % 2 == 0) //偶数行,从右往左
{
y = dep[p] - x + 1 + dep[p - 1];
dfs(y / 2, p - 1);
}
else
{
y = x;
dfs(dep[p - 1] + (dep[p - 1] + 1)/ 2 - y / 2, p - 1);
}
}
};
东哥
226. 翻转二叉树 - 力扣(LeetCode)
class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
//每个根节点的左右翻转
if(root == nullptr) return root;
invertTree(root->left);
invertTree(root->right);
swap(root->left, root->right);
return root;
}
};
117. 填充每个节点的下一个右侧节点指针 II - 力扣(LeetCode)
层序遍历
class Solution {
public:
//层序遍历
Node* connect(Node* root) {
queue<Node*> q;
q.push(root);
Node* last;
int cnt = 0;
while(!q.empty())
{
auto h = q.front();
cnt ++;
q.pop();
if(!h) continue;
if(pow(2, (int)log2(cnt)) != cnt) last->next = h;
last = h;
q.push(h->left);
q.push(h->right);
}
return root;
}
};
递归
class Solution {
public:
Node* connect(Node* root) {
if(root == NULL) return root;
con(root->left, root->right);
return root;
}
void con(Node* l, Node* r)
{
if(l == NULL) return;
l->next = r;
con(l->left, l->right);
con(r->left, r->right);
con(l->right, r->left);
}
};
114. 二叉树展开为链表 - 力扣(LeetCode)
class Solution {
public:
TreeNode* last;
void flatten(TreeNode* root) {
if(root == nullptr) return;
TreeNode* l = root->left;//一定要记录下左右节点,因为后边可能改变
TreeNode* r = root->right;
if(last != nullptr)
{
last->left = nullptr;
last->right = root;
}
last = root;
flatten(l);
flatten(r);
}
};
105. 从前序与中序遍历序列构造二叉树 - 力扣(LeetCode)
106. 从中序与后序遍历序列构造二叉树 - 力扣(LeetCode)
654. 最大二叉树 - 力扣(LeetCode)
class Solution {
public:
TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
return build(0, nums.size() - 1, nums);
}
TreeNode* build(int l, int r, vector<int>& nums)
{
if(l > r) return nullptr;
int p, ma = -1e9;
for(int i = l; i <= r; i ++ )
{
if(nums[i] > ma)
{
ma = nums[i];
p = i;
}
}
TreeNode* root = new TreeNode(nums[p]);
root->left = build(l, p - 1, nums);
root->right = build(p + 1, r, nums);
return root;
}
};
652. 寻找重复的子树 - 力扣(LeetCode)
//序列化问题
class Solution {
public:
unordered_map<string, int> mp;
vector<TreeNode*> ans;
vector<TreeNode*> findDuplicateSubtrees(TreeNode* root) {
xlh(root);
return ans;
}
string xlh(TreeNode* root)
{
if(root == nullptr) return "NULL ";
string res = "";
res.append(xlh(root->left));
res.append(xlh(root->right));//后序遍历
res.append(to_string(root->val) + " ");//序列化一定要加空格
mp[res] ++;//这种树的数量
if(mp[res] == 2)//
ans.push_back(root);
return res;
}
};
剑指 Offer 68 - II. 二叉树的最近公共祖先 - 力扣(LeetCode)
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if (root == NULL || p == root || q == root) {
return root;
}
TreeNode* l = lowestCommonAncestor(root->left, p, q);
TreeNode* r = lowestCommonAncestor(root->right, p, q);
return l == NULL ? r : (r == NULL ? l : root);
}
};
补充
101. 对称二叉树 - 力扣(LeetCode)
对于一个节点左右节点,如果他们对称,那么是左节点的右节点与右节点的左节点对称。
class Solution {
public:
bool check(TreeNode* l, TreeNode* r)
{
if(!l && !r) return true;
if(!l || !r) return false;
return l->val == r->val && check(l->left, r->right) && check(l->right, r->left);
}
bool isSymmetric(TreeNode* root) {
return check(root, root);
}
};
111. 二叉树的最小深度 - 力扣(LeetCode)
class Solution {
public:
int minDepth(TreeNode* root) {
if(!root) return 0;
if(!root->left && !root->right) return 1;//到达叶子节点
int m1 = minDepth(root->left);
int m2 = minDepth(root->right);
if(!root->left || !root->right) return m1 + m2 + 1;
return min(m1, m2) + 1;
}
};
236. 二叉树的最近公共祖先 - 力扣(LeetCode)
class Solution {
public:
unordered_map<TreeNode*, bool> mp;
TreeNode* ans;
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
//标记法, 第一次标记路径,第二次找到最后一个相交点
dfs1(root, p);
dfs2(root, q);
return ans;
}
bool dfs1(TreeNode* root, TreeNode* p)
{
if(root == NULL) return false;
if(root == p)
{
mp[root] = true;
return true;
}
return mp[root] = dfs1(root->left, p) || dfs1(root->right, p);
}
bool dfs2(TreeNode* root, TreeNode* q)
{
if(root == NULL || ans) return false;
if(root == q)
{
if(mp[root]) ans = root;
return true;
}
bool flag = dfs2(root->left, q) || dfs2(root->right, q);
if(flag && ans == NULL && mp[root])//表明是通向q的, 而且还没有答案, 而且是通向p的
{
ans = root;
}
return flag;
}
};
有三种情况,p、q在左树、p、q在右树、p、q一左一右。如果遇到pq那么就返回,如果一左一右就返回root,否则递归查找左右两个树
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if(!root) return NULL;
if(root == p || root == q) return root;
TreeNode* l = lowestCommonAncestor(root->left, p, q);
TreeNode* r = lowestCommonAncestor(root->right, p, q);
if(!l)//pq在右边
return r;
if(!r)//pq在左边
return l;
else return root;
}
};
337. 打家劫舍 III - 力扣(LeetCode)
树上dp
/**
* 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:
unordered_map<TreeNode*, unordered_map<int, int>> dp;
int rob(TreeNode* root) {
//打劫了父房子,不能打劫子房子
dfs(root);
return max(dp[root][0], dp[root][1]);
}
void dfs(TreeNode* root)
{
if(root == nullptr) return;
dfs(root->left);
dfs(root->right);
dp[root][0] += max(dp[root->left][0], dp[root->left][1]);
dp[root][0] += max(dp[root->right][0], dp[root->right][1]);
dp[root][1] += dp[root->left][0] + root->val;
dp[root][1] += dp[root->right][0];
}
};