输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
TreeNode* Convert(TreeNode* pRootOfTree)
{
//空节点直接返回null
if(pRootOfTree==nullptr)
return nullptr;
//单节点直接返回此节点
if(pRootOfTree->left==nullptr && pRootOfTree->right==nullptr)
return pRootOfTree;
//递归求出左子树和右子树的排序链表结果并返回头指针
TreeNode* leftHead = Convert(pRootOfTree->left);
TreeNode* rightHead = Convert(pRootOfTree->right);
//查找到左链表的最后一个节点
TreeNode* tmp = leftHead;
while(tmp!=nullptr && tmp->right!=nullptr){
tmp = tmp->right;
}
//左链表不为空,就连接左链表和该节点
if(leftHead != nullptr){
tmp->right = pRootOfTree;
pRootOfTree->left = tmp;
}
//右链表不为空,链接
if(rightHead!=nullptr){
pRootOfTree->right = rightHead;
rightHead->left = pRootOfTree;
}
//返回头结点
return leftHead==nullptr ? pRootOfTree:leftHead;
}
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
int length = vin.size();
if(length==0)
return nullptr;
struct TreeNode *head = new struct TreeNode(pre[0]);
int rootindex = 0;
vector<int> pre_left,pre_right,vin_left,vin_right;
for(int i=0;i<length;++i){
if(vin[i] == pre[0]){
rootindex = i;
break;
}
}
for(int i=0;i<rootindex;++i){
pre_left.push_back(pre[i+1]);
vin_left.push_back(vin[i]);
}
for(int i=rootindex+1;i<length;++i){
pre_right.push_back(pre[i]);
vin_right.push_back(vin[i]);
}
head->left = reConstructBinaryTree(pre_left,vin_left);
head->right = reConstructBinaryTree(pre_right,vin_right);
return head;
}
输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2)
{
if(pRoot2==nullptr || pRoot1==nullptr) //边界条件检查
return false;
TreeNode *tmp = nullptr;
queue<TreeNode*> q;
q.push(pRoot1);
while(!q.empty()){ //树的层序遍历
tmp = q.front();
q.pop();
if(doesT1HaveT2(tmp,pRoot2)) //判断以tmp为根节点的树的子结构是否包含pRoot2
return true;
if(tmp->left)
q.push(tmp->left);
if(tmp->right)
q.push(tmp->right);
}
return false;
};
/*判断树A中以R为根节点的子树是不是和树B具有相同的结构,可以这么判断:
如果根节点R的值不等于树B根节点的值,则以R为根节点的子树和树B不具有相同结构,
如果相同,再递归判断左右节点的值是否相同;递归终止条件是到达了树A的叶节点或者
树B的叶节点 (R表示层序遍历中遍历到的当前节点) */
bool doesT1HaveT2(TreeNode* p1, TreeNode* p2){
if(p2 == nullptr) //到达数B的叶节点说明树A以R为根节点的子树包含和树B相同的结构
return true;
if(p1 == nullptr) //还没有到达树B的叶节点时已经到达树A的叶节点说明与树A此叶节点
return false; //对应的树B的节点还有左或者右节点
if(p1->val != p2->val)
return false;
return doesT1HaveT2(p1->left,p2->left) && doesT1HaveT2(p1->right,p2->right);
}
输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。
int maxDepth(TreeNode* root) {
if(root==nullptr)
return 0;
int leftD = maxDepth(root->left);
int rightD = maxDepth(root->right);
return leftD>rightD ? leftD+1:rightD+1;
}
TreeNode* invertTree(TreeNode* root) {
if(root==nullptr)
return nullptr;
if(root->left==nullptr && root->right==nullptr)
return root;
TreeNode *left = invertTree(root->left);
TreeNode *right = invertTree(root->right);
root->left = right;
root->right = left;
return root;
}
给定两个二叉树,想象当你将它们中的一个覆盖到另一个上时,两个二叉树的一些节点便会重叠。
你需要将他们合并为一个新的二叉树。合并的规则是如果两个节点重叠,那么将他们的值相加作为节点合并后的新值,否则不为 NULL 的节点将直接作为新二叉树的节点。
TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) {
if(t1==nullptr && t2==nullptr)
return nullptr;
if(t1==nullptr)
return t2;
if(t2==nullptr)
return t1;
TreeNode *root = new TreeNode(t1->val+t2->val);
root->left = mergeTrees(t1->left,t2->left);
root->right = mergeTrees(t1->right,t2->right);
return root;
}
给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。
bool hasPathSum(TreeNode* root, int sum) {
if(root==nullptr)
return false;
if((root->left == nullptr) && (root->right == nullptr)){
if(sum == root->val)
return true;
}
return hasPathSum(root->left, sum-root->val) || hasPathSum(root->right, sum-root->val);
}
此题还有一个变形,打印出等于某个值的路径,见下题
给定一个二叉树,它的每个结点都存放着一个整数值。
找出路径和等于给定数值的路径总数。
路径不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。
二叉树不超过1000个节点,且节点数值范围是 [-1000000,1000000] 的整数。
int pathSum(TreeNode* root, int sum) {
if(root==nullptr)
return 0;
int ret = pathSumRoot(root,sum) + pathSum(root->left,sum) + pathSum(root->right,sum);
return ret;
}
int pathSumRoot(TreeNode *root,int sum){
if(root==nullptr)
return 0;
int ret = 0;
if(root->val==sum) ret++;
ret += pathSumRoot(root->left,sum-root->val) + pathSumRoot(root->right,sum-root->val);
return ret;
}
给定一个二叉树,检查它是否是镜像对称的。
例如,二叉树 [1,2,2,3,4,4,3] 是对称的。
但是 [1,2,2,null,3,null,3] 则不是镜像对称的:
bool isSymmetric(TreeNode* root) {
if(root==nullptr) return true;
return isSymmetric(root->left,root->right);
}
bool isSymmetric(TreeNode *left,TreeNode *right){
if(left==nullptr && right==nullptr) return true;
if(left==nullptr || right==nullptr) return false;
if(left->val != right->val) return false;
return isSymmetric(left->left,right->right) && isSymmetric(left->right,right->left);
}
给定一个二叉树,找出其最小深度。
最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
https://leetcode.com/problems/minimum-depth-of-binary-tree/
int minDepth(TreeNode* root) {
if(root==nullptr) return 0;
int left = minDepth(root->left);
int right = minDepth(root->right);
if(left==0 || right==0) return left+right+1;
return min(left,right) + 1;
}
计算给定二叉树的所有左叶子之和。
https://leetcode.com/problems/sum-of-left-leaves/description/
int sumOfLeftLeaves(TreeNode* root) {
if(root==nullptr) return 0;
if(isLeaf(root->left)) return root->left->val + sumOfLeftLeaves(root->right);
return sumOfLeftLeaves(root->left) + sumOfLeftLeaves(root->right);
}
bool isLeaf(TreeNode *root){
if(root==nullptr) return false;
return root->left==nullptr && root->right==nullptr;
}
使用 BFS 进行层次遍历。只需记下每层的节点数目,用一个队列即可完成每层输出。
Given a non-empty binary tree, return the average value of the nodes on each level in the form of an array.
https://leetcode.com/problems/average-of-levels-in-binary-tree/
vector<double> averageOfLevels(TreeNode* root) {
if(root==nullptr) return vector<double>(0);
queue<TreeNode*> q;
vector<double> v;
q.push(root);
int currentNum = 1;
int nextNum = 0;
double avg = 0.0;
while(!q.empty()){
nextNum = 0;
avg = 0;
int i = currentNum;
while(i){
TreeNode *tmp = q.front();
q.pop();
avg += tmp->val;
if(tmp->left!=nullptr){
q.push(tmp->left);
nextNum++;
}
if(tmp->right!=nullptr){
q.push(tmp->right);
nextNum++;
}
--i;
}
avg /= currentNum;
v.push_back(avg);
currentNum = nextNum;
}
return v;
}
Given a non-empty binary tree, return the average value of the nodes on each level in the form of an array.
https://leetcode.com/problems/average-of-levels-in-binary-tree/
int findBottomLeftValue(TreeNode* root) {
queue<TreeNode*> q;
q.push(root);
while(!q.empty()){
int num = q.size();
int i = num;
TreeNode *leftNode = nullptr;
while(i){
TreeNode *tmp = q.front();
q.pop();
if(i==num)
leftNode = tmp;
if(tmp->left!=nullptr) q.push(tmp->left);
if(tmp->right!=nullptr) q.push(tmp->right);
--i;
}
if(q.empty())
return leftNode->val;
}
return -1;
}
上面两个题都是同样的思路,用队列存储每层的节点,然后根据每层的节点数输出。
Given a binary search tree and the lowest and highest boundaries as L and R, trim the tree so that all its elements lies in [L, R] (R >= L). You might need to change the root of the tree, so the result should return the new root of the trimmed binary search tree.
https://leetcode.com/problems/trim-a-binary-search-tree/
TreeNode* trimBST(TreeNode* root, int L, int R) {
if(root==nullptr) return nullptr;
if(root->val > R) return trimBST(root->left,L,R);
if(root->val < L) return trimBST(root->right,L,R);
root->left = trimBST(root->left,L,R);
root->right = trimBST(root->right,L,R);
return root;
}
https://leetcode.com/problems/kth-smallest-element-in-a-bst/
class Solution {
public:
int kthSmallest(TreeNode* root, int k) {
preOrder(root,k);
return result;
}
void preOrder(TreeNode* root,int k){
if(root){
preOrder(root->left,k);
time++;
if(time==k){
result = root->val;
}
preOrder(root->right,k);
}
}
private:
int time=0; //类内初始化值
int result;
};
Given a Binary Search Tree (BST), convert it to a Greater Tree such that every key of the original BST is changed to the original key plus sum of all keys greater than the original key in BST.
https://leetcode.com/problems/convert-bst-to-greater-tree/
class Solution {
public:
TreeNode* convertBST(TreeNode* root) {
inOrder(root);
return root;
}
void inOrder(TreeNode* root){
if(root){
inOrder(root->right);
root->val += sum;
sum = root->val;
inOrder(root->left);
}
}
private:
int sum=0;
};
https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-search-tree/
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if(root->val > p->val && root->val > q->val){
return lowestCommonAncestor(root->left,p,q);
}
if(root->val < p->val && root->val < q->val){
return lowestCommonAncestor(root->right,p,q);
}
return root;
}
https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tree/description/
https://leetcode.com/problems/convert-sorted-array-to-binary-search-tree/
TreeNode* sortedArrayToBST(vector<int>& nums) {
int size = nums.size();
if(size==0)
return nullptr;
int middle = (size-1)/2;
int middleVal = nums[middle];
TreeNode* node = new TreeNode(middleVal);
vector<int> leftnums(nums.begin(),nums.begin()+middle);
vector<int> rightnums(nums.begin()+middle+1,nums.end());
TreeNode* left = sortedArrayToBST(leftnums);
TreeNode* right = sortedArrayToBST(rightnums);
node->left = left;
node->right = right;
return node;
}
https://leetcode.com/problems/convert-sorted-list-to-binary-search-tree/description/
https://leetcode.com/problems/two-sum-iv-input-is-a-bst/
将遍历过的值放入一个set中,然后查找target-当前节点值 是否在set中
class Solution {
public:
bool findTarget(TreeNode* root, int k) {
traversal(root,k);
return ret;
}
void traversal(TreeNode* root,int k){
if(root){
traversal(root->left,k);
if(s.find(k-root->val) != s.end()){
ret = true;
return;
}
s.insert(root->val);
traversal(root->right,k);
}
}
private:
unordered_set<int> s;
bool ret=false;
};
vector<int> preorderTraversal(TreeNode* root) {
vector<int> v;
stack<TreeNode*> s;
s.push(root);
while(!s.empty()){
TreeNode* tmp = s.top();
s.pop();
if(tmp==nullptr) continue;
v.push_back(tmp->val);
s.push(tmp->right); //先右后左保证出栈顺序
s.push(tmp->left);
}
return v;
}
前序遍历是root->left->right,压栈顺序是root->right->left,后序遍历是left->right->root,如果压栈顺序是root->left->right,则输出顺序是root->right->left,这个顺序刚好和后序遍历相反,最后在翻转即可。
vector<int> inorderTraversal(TreeNode* root) {
vector<int> v;
if(root==nullptr) return v;
stack<TreeNode*> s;
//s.push(root);
TreeNode* cur = root;
while(cur!=nullptr || !s.empty()){
while(cur!=nullptr){
s.push(cur);
cur = cur->left;
}
TreeNode* tmp = s.top();
s.pop();
v.push_back(tmp->val);
cur = tmp->right;
}
return v;
}
查找根节点的最左子树,沿途一直将节点压栈,直到找到最左子树,然后弹栈,访问弹出节点的值,再对该节点的右节点执行前面的过程,直到栈为空。