步骤
/**
* 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) {
path.clear();
if(root == nullptr) return 0;//剔除
//中节点
path.push_back(root->val);
travelsal(root);//回溯
return result;
}
private:
int result = 0;//记录最终结果
vector<int> path;//记录单路径结果
//单路径结果保存在数组 需要转成int
int vector2Int(const vector<int>& vec)
{
int sum = 0;
for(int i=0; i<vec.size(); i++)
{
//数字构成是节点拼接 1->2 --- 12 所以要乘10
sum = sum * 10 + vec[i];
}
return sum;
}
//回溯
void travelsal(TreeNode* cur)
{
//遇到叶子节点 保存结果并返回
if(!cur->left && !cur->right)
{
//单路径节点值拼接
result += vector2Int(path);
return;
}
//前序遍历 中左右
if(cur->left)//左节点
{
path.push_back(cur->left->val);//保存单路径结果
travelsal(cur->left);//递归
path.pop_back();//回溯
}
if(cur->right)
{
path.push_back(cur->right->val);
travelsal(cur->right);
path.pop_back();
}
return;
}
};
/**
* 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) {
//2.广度优先遍历
return BFS(root, 0);
}
private:
//2.广度优先遍历
int BFS(TreeNode* cur, int sum)
{
if(!cur) return 0;//空树
//当前层遍历 遇到叶子节点 结束递归
else if(!cur->left && !cur->right) return sum * 10 + cur->val;
return BFS(cur->left, sum * 10 + cur->val) + BFS(cur->right, sum * 10 + cur->val);
}
};
步骤
注意回溯和递归要永远一起,一个递归,对应一个回溯,是一对一的关系
写法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:
bool hasPathSum(TreeNode* root, int targetSum) {
//1.深度优先遍历 递归 写法1
if(root == nullptr) return false;
return travelsal(root, targetSum - root->val);//中节点
}
private:
//1.深度优先遍历 递归
bool travelsal(TreeNode* cur, int count)
{
//遍历到叶子节点且count为0 找到路径
if(!cur->left && !cur->right && count == 0) return true;
//遍历到叶子节点且count不为0 没有找到路径
if(!cur->left && !cur->right && count != 0) return false;
//左节点
if(cur->left)
{
count -= cur->left->val;
if(travelsal(cur->left, count)) return true;//递归
count += cur->left->val;//回溯
}
//右节点
if(cur->right)
{
count -= cur->right->val;
if(travelsal(cur->right, count)) return true;
count += cur->right->val;
}
return false;
}
};
写法2,简化代码
/**
* 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) {
//1.深度优先遍历 递归 写法2
if(!root) return false;//空树
if(!root->left && !root->right && targetSum == root->val) return true;//遍历到叶子节点且找到路径
//没有遍历到叶子节点 继续递归
//遍历左右节点 targetSum减去上一个节点值
return hasPathSum(root->left, targetSum - root->val) || hasPathSum(root->right, targetSum - root->val);
}
};
用栈模拟递归,栈里一个元素要记录该节点指针和从头结点到该节点的路径数值总和。
用pair结构来存放这个栈里的元素,定义为:pair
/**
* 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) {
//2.迭代 栈模拟 pair对组
if(root == nullptr) return false;
//栈里要放的是pair<节点指针,路径数值>
stack<pair<TreeNode*, int>> st;
st.push(pair<TreeNode*, int>(root, root->val));//中节点
while(!st.empty())
{
//获取栈顶元素
pair<TreeNode*, int> node = st.top();
st.pop();//弹出
//到叶子节点且路径和为目标值 找到路径
if(!node.first->left && !node.first->right && node.second == targetSum) return true;
if(node.first->left)//左节点
{
//栈保存(左节点,左节点值+累加和)
st.push(pair<TreeNode*, int>(node.first->left, node.first->left->val + node.second));
}
if(node.first->right)
{
st.push(pair<TreeNode*, int>(node.first->right, node.first->right->val + node.second));
}
}
return false;
}
};
深度优先遍历BFS 步骤
注意回溯和递归要永远一起,一个递归,对应一个回溯,是一对一的关系
写法1
这种写法,有两个回溯,一个是计数器count,还有一个是path,路径回溯
/**
* 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<vector<int>> pathSum(TreeNode* root, int targetSum) {
path.clear();
result.clear();
if(root == nullptr) return result;
//1.深度优先遍历BFS 写法1
path.push_back(root->val);//中节点
travelsal(root, targetSum - root->val);
return result;
}
private:
vector<int> path;//单条路径
vector<vector<int>> result;//所有结果
void travelsal(TreeNode* cur, int count)
{
if(!cur->left && !cur->right && count == 0)
{
result.push_back(path);
return;
}
if(cur->left)
{
path.push_back(cur->left->val);//保存当前节点值
count -= cur->left->val;//计数
travelsal(cur->left, count);//递归
count += cur->left->val;//回溯
path.pop_back();//回溯
}
if(cur->right)
{
path.push_back(cur->right->val);
count -= cur->right->val;
travelsal(cur->right, count);
count += cur->right->val;
path.pop_back();
}
return;
}
};
写法2
/**
* 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<vector<int>> pathSum(TreeNode* root, int targetSum) {
path.clear();
result.clear();
//1.深度优先遍历BFS 写法2
dfs(root, targetSum);
return result;
}
private:
vector<int> path;//单条路径
vector<vector<int>> result;//所有结果
//1.深度优先遍历BFS 写法2
void dfs(TreeNode* cur, int count)
{
if(!cur) return;
path.push_back(cur->val);
count -= cur->val;
if(!cur->left && !cur->right && count==0) result.push_back(path);
dfs(cur->left, count);//递归
dfs(cur->right, count);//递归
path.pop_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:
TreeNode* balanceBST(TreeNode* root) {
dfs(root);
return getBalanceTree(vec, 0, vec.size()-1);
}
private:
//1.有序树转成有序数组 中序遍历 节点值大小排序是左中右
vector<int> vec;
void dfs(TreeNode* cur)
{
if(cur == nullptr) return;
dfs(cur->left);//左节点
vec.push_back(cur->val);
dfs(cur->right);
}
//2.有序数组转成平衡树
TreeNode* getBalanceTree(vector<int>& vec, int start, int end)
{
if(start > end) return nullptr;
int mid = start + (end - start) / 2;//头节点值
TreeNode* root = new TreeNode(vec[mid]);//头节点
root->left = getBalanceTree(vec, start, mid-1);
root->right = getBalanceTree(vec, mid+1, end);
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:
bool isSameTree(TreeNode* p, TreeNode* q) {
if(p == nullptr && q == nullptr) return true;
else if(p == nullptr || q == nullptr) return false;
else if(p->val != q->val) return false;
//树不空 比较两个子树
bool left = isSameTree(p->left, q->left);//递归
bool right = isSameTree(p->right, q->right);//递归
return left && 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 isSameTree(TreeNode* p, TreeNode* q) {
//2.BFS 迭代法 队列
if(p == nullptr && q == nullptr) return true;
else if(p == nullptr || q == nullptr) return false;
queue<TreeNode*> que;
que.push(p);
que.push(q);
while(!que.empty())
{
//分别获取两个数的节点
TreeNode* nodep = que.front(); que.pop();
TreeNode* nodeq = que.front(); que.pop();
//都是空节点跳过当前两个节点 下一轮迭代
if(!nodep && !nodeq) continue;
//有一个节点是空指针 或者两个节点值不相等 false
if(!nodep || !nodeq || (nodep->val != nodeq->val)) return false;
//更新队列节点
que.push(nodep->left); que.push(nodeq->left);
que.push(nodep->right); que.push(nodeq->right);
}
return true;
}
};
/*
// Definition for a Node.
class Node {
public:
int val;
Node* left;
Node* right;
Node* next;
Node() : val(0), left(NULL), right(NULL), next(NULL) {}
Node(int _val) : val(_val), left(NULL), right(NULL), next(NULL) {}
Node(int _val, Node* _left, Node* _right, Node* _next)
: val(_val), left(_left), right(_right), next(_next) {}
};
*/
class Solution {
public:
Node* connect(Node* root) {
//1.BFS 队列
queue<Node*> que;
if(root != NULL) que.push(root);
while(!que.empty())
{
//依次遍历每行的节点
int size = que.size();
for(int i=0; i<size; i++)
{
//获取当前节点
Node* cur = que.front();
que.pop();
//如果不是最后一个节点 指向下一个节点,否则指向nullptr
if(i != size-1) cur->next = que.front();
else cur->next = nullptr;
//更新队列节点
if(cur->left != nullptr) que.push(cur->left);
if(cur->right != nullptr) que.push(cur->right);
}
}
return root;
}
};
题目进阶要求就是要使用递归,时间复杂度 O ( N ) O(N) O(N),空间复杂度 O ( 1 ) O(1) O(1)
/*
// Definition for a Node.
class Node {
public:
int val;
Node* left;
Node* right;
Node* next;
Node() : val(0), left(NULL), right(NULL), next(NULL) {}
Node(int _val) : val(_val), left(NULL), right(NULL), next(NULL) {}
Node(int _val, Node* _left, Node* _right, Node* _next)
: val(_val), left(_left), right(_right), next(_next) {}
};
*/
class Solution {
public:
Node* connect(Node* root) {
//2.DFS
dfs(root);
return root;
}
private:
void dfs(Node* cur)
{
if(cur == nullptr) return;
//中节点 处理
if(cur->left) cur->left->next = cur->right;//左孩子
if(cur->right)//右孩子
{
if(cur->next) cur->right->next = cur->next->left;
else cur->right->next = nullptr;
}
dfs(cur->left);
dfs(cur->right);
}
};
1. 二叉树遍历方式:
2. 二叉树返回值:
递归函数什么时候需要返回值?什么时候不需要返回值?这里总结如下三点:
3. 二叉搜索树具有如下特征:
4. 二叉搜索树的应用: 与有序数组的转化、验证二叉搜索树、与平衡树的转化
5. 二叉平衡树的特征: 一棵二叉搜索树中,每个节点的两棵子树高度差不超过 1
6. 完美二叉树的特征 ——题116