二叉树定义
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){}
};
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
后序遍历
if(root==nullptr)return;
dfs(root->left);
dfs(root->right);
res.push_back(root->val);
  • 1.
  • 2.
  • 3.
  • 4.
中序遍历
if(root==nullptr)return;
dfs(root->left);
res.push_back(root->val);
dfs(root->right);
  • 1.
  • 2.
  • 3.
  • 4.
先序遍历
if(root==nullptr)return;
res.push_back(root->val);
dfs(root->left);
dfs(root->right);
  • 1.
  • 2.
  • 3.
  • 4.
层级遍历
if(root==null)return;
q;
q.add(root);
while(q不空){
   int size=q.size();
   for(int i=0;i<size;i++){
        q.pop();
        if(q.left)q.add(q.left);
        if(q.right)q.add(q.right);
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
之字打印二叉树

中序遍历后按层反转vector

二叉搜索树转循环链表

//二叉搜索树转双向循环链表(中序遍历)

vector<Node*> list; // 创建一个列表来保存中序遍历的节点  
dfs(root, list); // 执行中序遍历,并将节点添加到列表中  
n = list.size(); // 获取列表中节点的数量  
if (n == 0) return nullptr; // 如果列表为空,则返回空指针  
    // 将列表中的节点连接成双向循环链表  
for (int i = 0; i < n; ++i) {  
   list[i]->left = list[(i - 1 + n) % n]; // 设置左指针为前一个节点  
   list[i]->right = list[(i + 1) % n];    // 设置右指针为后一个节点  
 }
return list[0]; // 返回链表的头节点(双向循环链表的任意节点都可以作为头节点)
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
二叉树的最大路径和(*)

路径为一条从树中任意节点出发,达到任意节点的序列(不一定经过根节点)

算法复习:二叉树合集翻转二叉树二叉树的序列化和反序列化(剑指 Offer 37)LeetCode 654 最大二叉树二叉树的所有_子树

为了便于理解,给出示例。

class Solution {  
private:  
    int maxSum; // 全局变量,记录最大路径和  
    // 辅助函数,返回以当前节点为根的子树中的最大路径和  
    int dfs(TreeNode* root) {  
        if (root == nullptr) return 0;  
        // 递归计算左子树和右子树的最大路径和  
        int leftSum = max(dfs(root->left), 0);  
        int rightSum = max(dfs(root->right), 0);  
        // 计算经过当前节点的最大路径和,并更新全局最大路径和  
        int currSum = root->val + leftSum + rightSum;  
        maxSum = max(maxSum, currSum);  
        // 返回以当前节点为根的子树中的最大路径和(注意:这里只考虑经过当前节点的路径)  
        return root->val + max(leftSum, rightSum);  
    }  
public:  
    int maxPathSum(TreeNode* root) {  
        maxSum = INT_MIN; // 初始化最大路径和为最小整数值  
        dfs(root); // 从根节点开始深度优先搜索  
        return maxSum; // 返回最大路径和  
    }  
};
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
判断对称二叉树
// 判断两棵树是否对称  
bool isSymmetric(TreeNode* l, TreeNode* r)
    // 如果两个节点都为空,则是对称的
    if (l 空&& r空)return true;  
    // 如果只有一个节点为空,或者两个节点都不为空但值不相等,则不是对称的  
    if (l == nullptr || r == nullptr || l->val != r->val)return false;  
    // 递归判断左子树和右子树是否对称  
    return isSymmetric(l->left, r->right) && isSymmetric(l->right, r->left);  
  
// 判断一棵二叉树是否是对称二叉树  
bool isSymmetric(TreeNode* root) {  
    // 空树是对称的  
    if (root == nullptr) return true;  
    // 对于非空树,只需要判断根节点的左右子树是否对称  
    return isSymmetric(root->left, root->right);  
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.

时间复杂度是 O(n),因为需要遍历二叉树的每个节点一次。在递归过程中,对每个节点的左子树和右子树进行对称性的比较。对于每个节点,进行常数时间的值比较,并递归地检查其子节点。由于每个节点只会被访问一次,时间复杂度是线性的。

判断平衡二叉树
// 计算树的高度  
h(root):  
    if root == null:  
        return 0  
    return 1 + max(h(root.left), h(root.right))  
// 判断平衡二叉树  
isB(root):  
    if root == null:  
        return true  
    return abs(h(root.left) - h(root.right)) <= 1 && isB(root.left) && isB(root.right)
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
判断是否是相同的树
// 判断两个树是否相同  
isSame(p, q):  
    // 如果两个树都为空,则它们是相同的  
    if p is null and q is null:  
        return true  
    // 如果一个树为空而另一个不为空,或者它们的根节点值不相等,则它们不是相同的树  
    if p is null or q is null or p.val != q.val:  
        return false  
    // 递归地检查左子树和右子树是否相同  
    return isSame(p.left, q.left) and isSame(p.right, q.right)
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

时间复杂度O(n)

合并二叉树

   两个二叉树对应位置相加,如果有一个为空视为0,返回新的二叉树

function mergeTrees(root1, root2):  
    // 创建一个新的根节点,初始值为0  
    root = new TreeNode(0)  
    // 如果两个根节点都为空,则返回空  
    if root1 is null and root2 is null:  
        return null  
    // 如果root1为空,返回root2  
    if root1 is null:  
        return root2  
    // 如果root2为空,返回root1  
    if root2 is null:  
        return root1  
    // 合并两个根节点的值  
    root.val = root1.val + root2.val  
    // 递归地合并左子树和右子树  
    root.left = mergeTrees(root1.left, root2.left)  
    root.right = mergeTrees(root1.right, root2.right) 
    // 返回合并后的新树的根节点  
    return root
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
左叶子之和

带标记信息的dfs:用flag标记当前节点是父节点的左节点还是右节点,1左2右

sum(root):
     return dfs(root,0)

dfs (root, flag):
     if(root==null) return 0
     if(root.left==null&&root.right==null&&flag==1)return root.val;
     return dfs(root.left,1)+dfs(root.right,2);
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
最大深度
D(root):
  root==null return 0
  return max(D(left),D(right))+1
  • 1.
  • 2.
  • 3.
最小深度

最小深度是从根节点到最近叶子节点的最短路径上的节点数量。

需要讨论三种特殊情况注意

算法复习:二叉树合集翻转二叉树二叉树的序列化和反序列化(剑指 Offer 37)LeetCode 654 最大二叉树二叉树的所有_数据结构_02

答案为5。

D(root):
  root空 return 0
  左空右不空 return D(right)+1
  右空左不空 return D(left)+1
  return min(D(left),D(right))+1
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
最近公共祖先
find(root,p,q)
         //p,q直接是root
         root=null||root=p||root=q return root;
         left=find(root.left,p,q)
         right=find(root.right,p,q)
         左子树找不到返回right
         if left=null:return right
         右子树找不到返回left
         if right=null:return left
         p,q在root两侧返回root
         return root
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
构建二叉树
build(nums,int l,int r):
       nums:i为根节点,左区间构造左子树,右区间构造右子树
       if(l>r)return null;
       TreeNode root=new nums[i]
       root.left=build(nums,l,i-1)
       root.right=build(nums,i+1,r)
       return root
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
由有序数组构造高度平衡的二叉搜索树
build nums,l,r:
    if l>r return;
        root=new nums[mid]//使用中间的数构造
        root.left=build(nums,l,mid-1)
        root.right=build(nums,mid+1,r)
        return root
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
 由前序遍历和中序遍历构建二叉树

      前序遍历:根[左][右]

      中序遍历:[左]根[右]

       map存索引,中序找根,求左区间长度

map[vin[i]] = i 
//在中序遍历中迅速找到根节点,可以使用哈希表
build(pre,l1,r1,vin,l2,r2):
if r1>l1||r2>l2:return
root=new pre[l1];
int idx=map[pre[l1]]
int len=idx-1-l2+1;
root.left=build(pre,l1+1,l1+1+len-1,vin,l2,idx-1);
root.right=build(pre,l1+l+len-1+1,r1,vin,idx+1,r2);
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

树的子结构 

isSubTree(A,B)://判断B是否是A的子结构

思路:先序遍历A,每个节点分别判断以B为根的树是否是该树的子树

//如果B是null或者A是null
      if(A==null||B==null)return false
//判断以B为根的树是否是以A为根的树的子树
     dfs(A,B)|| isSubTree(A.left,B) || isSubTree(A.right,B)
dfs(A,B):
   if(B==null)return true
   if(A==null)return false
   return A.val==B.val&&dfs(A.left,B.left)&&dfs(A.right,B.right)
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.

LeetCode129 求根节点到叶节点数字之和 

输入:root = [1,2,3]。输出:25。从根到叶子节点路径 1->2 代表数字 12。从根到叶子节点路径 1->3 代表数字 13。数字总和 = 12 + 13 = 25。

root,sum表示[已经]遍历root节点所有sum的值???

dfs(root,sum):
   叶子节点为空,0;
   只有叶子节点sum*10+root->val;
   return dfs(root.left,sum*10+root.left.val)+dfs(root.right,sum*10+root.right.val);
  • 1.
  • 2.
  • 3.
  • 4.
判断完全二叉树
在所有叶子节点下补上两个null.

while:q
      t=q.poll
      if(t==null)continue;
      else
        q.add(t.left);
        q.add(t.right);
  完全二叉树:所有叶子节点补上Null之后,层序遍历中一定满足非空节点在左面,空节点在右面。
  如果非空节点中有一个空节点,那么不是完全二叉树。
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
判断二叉搜索树
bool isValidBST(TreeNode* root, long long min_val = LONG_MIN, long long max_val = LONG_MAX) {
 if (root == NULL) return true; // 空树是有效的
 if (root->val <= min_val || root->val >= max_val) return false; // 当前节点值超出范围
    // 递归检查左右子树
 return isValidBST(root->left, min_val, root->val) && isValidBST(root->right, root->val, max_val);
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

  中序遍历有序;list存放中序遍历的序列

二叉搜索树下一个节点:

  如果root.val<=p.val说明下一个节点一定在root右子树中

  否则节点要么 在左子树中,要么是root

dfs(root,p):
     if root==null:return null
     if(root.val<=p.val)dfs(root.right,p);
     TreeNode node=dfs(root.left,p);
     return node==null?root:node;
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

二叉搜索树的插入

insert(root,val):
     root==null return new root(val)
     if root.val>val: root.left=insert(root.left,val);
     else root.right=insert(root.right,val);
     return root
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

二叉搜索树的搜索

search(root,val):
   if root==null: return null
   if root.val==val:return root;
   else root.val>val: search(root.left,val);
   else root.val<val: search(root.right,val);
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

二叉搜索树第k大节点 后序遍历k次停下返回

dfs(root):
   if(root==nullptr)return;
   dfs(root.right);
   cnt++;
   if(cnt==k){
      res=root.val;
      return;
   }
   dfs(root.left);
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

二叉搜索树转平衡二叉树

传入0,n-1
中序遍历然后对这个有序序列递归建树,
left= l,mid-1
right=mid+1,r
root=mid
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

二叉搜索树转换为累加数BST节点的权值变为大于等于节点权值之和

节点的权值变为中序遍历的后缀和,即右中左序列的前缀和

int pre = 0; // 记录前一个节点的数值
void traversal(TreeNode* cur): 
// 右中左遍历
    if (cur == NULL)return;
    traversal(cur->right);
    cur->val += pre;
    pre = cur->val;
    traversal(cur->left);
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.

修剪二叉搜索树

    删除节点使BST所有节点都在[low,high]范围内:

trim(root,low,high)if root.val>high://删除右子树
           root=root.left
           return trim(root,low,high)
      else if root.val<low://删除左子树
           root=root.right
           return trim(root,low,high)
      else://对左子树和右子树修剪
           root.left=trim(root.left,low,high)
           root.right=trim(root.right,low,high)
           return root
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

二叉搜索树的删除: 

//不等于在左右子树中删除
//等于如果左右子树不全为空,返回另一颗子树
//如果全部为空,找右子树的最左叶子节点node
 delete(root,val):
    if root=null return null;
    if root.val>val root.left=delete(root.left,val);
    else if root.val<val root.right=delete(root.right,val);
    else
       if root.left=null return root.right
       if root.right=null return root.left
       TreeNode t=root.right;
       while(t.left!=null)t=t.left;
       t.left=root.left;
       root=root.right;
    return root
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.

翻转二叉树

TreeNode* invertTree(TreeNode* root):
  if root空或root为叶子节点
  //递归体
  TreeNode *l=invertTree(root->left);//递归翻转左子树,返回翻转后 左子树的根节点
  TreeNode *r=invertTree(root->right);//递归翻转右子树,返回翻转后 右子树的根节点
  root->right=l;
  root->left=r;
  return root;
 

//LeetCode 226
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

二叉树展开为链表

把左子树展开成单链表,根节点指向左孩子节点,把右子树展开成单链表。左子树单链表的尾结点指向右子树的头结点(左子树不为空)。当左子树为空时,根节点直接指向右子树展开的单链表的头结点

void flatten(TreeNode* root):

if(root空 或者 root为叶子节点): return

//展开左子树
TreeNode *l=root->left;
flatten(l);

//展开右子树
TreeNode *r=root->right;
flatten(r);

//释放根节点
root->left=NULL;
root->right=NULL;

root->right=l;

TreeNode *p=l;
if p:
while(p->right)p=p->right;
p->right=r;

else:
    root->right=r; 

return;


//LeetCode 114
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.

二叉树的序列化和反序列化(剑指 Offer 37)

void rserialize(TreeNode *root,string &str)
{
  if(root==NULL)
 {
  str+="None,";
 }
else
{
  str+=to_string(root->val)+",";
  rserialize(root->left,str);
  rserialize(root->right,str);
}
 
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
//根据链表建树
 TreeNode* rdeserialize(list<string>& dataArray) {
        if (dataArray.front() == "None") {
            dataArray.erase(dataArray.begin());
            return nullptr;
        }//如果链表为空,则返回空树
 
        TreeNode* root = new TreeNode(stoi(dataArray.front()));
        dataArray.erase(dataArray.begin());//根节点
        root->left = rdeserialize(dataArray);//左子树
        root->right = rdeserialize(dataArray);//右子树
        return root;
    }
 
 
//反序列化
    TreeNode* deserialize(string data) {
        list<string> dataArray;
        string str;
//把二叉树节点序列化的值加入链表
        for (auto& ch : data) {
            if (ch == ',') {
                dataArray.push_back(str);
                str.clear();
            } else {
                str.push_back(ch);
            }
        }
        if (!str.empty()) {
            dataArray.push_back(str);
            str.clear();
        }
        return rdeserialize(dataArray);
    }
 
 
来源:力扣(LeetCode)
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.

剑指offer:二叉树中序遍历的下一个节点

struct TreeLinkNode {
    int val;
    struct TreeLinkNode *left;
    struct TreeLinkNode *right;
    struct TreeLinkNode *next;
    TreeLinkNode(int x) :val(x), left(NULL), right(NULL), next(NULL) {
        
    }
};
*/
class Solution {
public:
    vector<TreeLinkNode*>vin;
    void dfs(TreeLinkNode*root){
        if(root==NULL){
            return;
        }
        dfs(root->left);
         vin.push_back(root);
        dfs(root->right);
    }
    TreeLinkNode* GetNext(TreeLinkNode* pNode) {
        TreeLinkNode *root=nullptr;
        TreeLinkNode *tmp=pNode;
        while(tmp){
            root=tmp;
            tmp=tmp->next;
        }
        dfs(root);
        for(int i=0;i<vin.size();i++){
            if(vin[i]==pNode&&i!=vin.size()-1){
                return vin[i+1];
            }
         }
        return NULL;
    }
};
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.

【二叉树】993. Cousins in Binary Tree

题意:定义堂兄弟节点:层数相同,但是父节点不相同。

思路:dfs,记录层数和父节点的值。

返回一个数组,里面存层数和父节点的值

class Solution {
    public boolean isCousins(TreeNode root, int x, int y) {
        int[] a = dfs(root,x,0,-1);
        int[] b = dfs(root,y,0,-1);
        if(a[0] == b[0]){
            return a[1] != b[1];
        }
        return false;
    }
    int[] dfs(TreeNode root,int x,int level,int p){
        if(root == null){
            return new int[]{};
        }
        if(root.val == x){
            return new int[]{level,p};
        }
        int[]a = dfs(root.left,x,level+1,root.val);
        int[]b = dfs(root.right,x,level+1,root.val);
        if(a.length == 0) return b;
        return a;
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.

LeetCode 654 最大二叉树

class Solution {
public:
    TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
if(nums.size()==0)
{
    return NULL;
}
if(nums.size()==1)
{
    TreeNode *root=new TreeNode(nums[0]);
   
    return root;
}
 
 
int max_index=0;
int max=-1;
for(int i=0;i<nums.size();i++)
{
    if(max<nums[i])
    {
        max=nums[i];
        max_index=i;
    }
}
TreeNode *root=new TreeNode;
root->val=max;
vector<int>nums1(nums.begin(),nums.begin()+max_index);
vector<int>nums2(nums.begin()+max_index+1,nums.end());
TreeNode *l=constructMaximumBinaryTree(nums1);
TreeNode *r=constructMaximumBinaryTree(nums2);
root->left=l;
root->right=r;
return root;}
};
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.

递归出口: 

(1)nums数组为空,返回空节点

(2)nums数组个数为1,返回用该值构造的根节点

递归体:

找到nums最大值,构造根节点

找出nums中最大值max和最大值下标max_index 构造根节点

数组分为最大值左面的数组nums1,最大值右面的数组nums2

二叉树的所有路径(LeetCode 257)

1.递归
递归函数声明:  

vector<string> binaryTreePaths(TreeNode* root) ;

递归出口:

(1)如果根节点为空,返回 “  ”

  (2)  如果根节点不为空且根节点的左右节点都为空,返回“root->val”

递归体:

  如果根节点不为空且根节点的左右节点不全为空,递归求出左子树的路径和右子树的路径,

 在左子树和右子树所有路径前加上“(root->val)->”

c++中string操作:

 vector<string>s,s为存放字符串的动态数组

s=s1+s2为字符串的拼接

to_string(n) 把整数n转换成字符串

class Solution {
public:
    vector<string> binaryTreePaths(TreeNode* root) {
vector<string>res;
if(root==NULL)
{
    return res;
}
if(!root->left&&!root->right)
{
    string str;
    str+=to_string(root->val);
    res.push_back(str);
    return res;
}
string s;
s+=to_string(root->val)+"->";//把s加到l,r的每一个字符数组中
vector<string>l;
vector<string>r;
l=binaryTreePaths(root->left);//l为以左子树为根节点的路径结果
r=binaryTreePaths(root->right);//r为以右子树为根节点的路径结果
 
for(int i=0;i<l.size();i++)
{
    res.push_back(s+l[i]);
}
for(int i=0;i<r.size();i++)
{
    res.push_back(s+r[i]);
}
return res;
    }
};
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.

剑指 Offer II 047. 二叉树剪枝

TreeNode* pruneTree(TreeNode* root) {
       if(root==NULL) return NULL;
       if(!root->left&&!root->right&&root->val==0) return NULL;
       TreeNode *l=pruneTree(root->left);
       TreeNode *r=pruneTree(root->right);
       root->left=l;
       root->right=r;
       if(!root->left&&!root->right&&root->val==0) return NULL;
       return root;
    }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

注意顺序。

求完全二叉树结点个数(leetcode 222)

class Solution {
public:
    int countNodes(TreeNode* root) {
if(root==NULL)
{
    return 0;
}
if(!root->left&&!root->right)
{
    return 1;
}
return 1+countNodes(root->left)+countNodes(root->right);
    }
};
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
平衡二叉树的判定(LeetCode 110)

递归出口:

(1)根节点为空,返回真   (2)根节点左右孩子节点都为空,返回真

递归体:

根节点左右孩子节点不全为空,递归判断左右子树是否为平衡二叉树。

如果 左右子树有一个不是平衡二叉树,返回假。

如果 左右子树都是平衡二叉树,且左右子树的高度差小于等于1,返回真。

class Solution {
public: 
   int depth(TreeNode *root)//以root为根节点二叉树的高度
   {
       if(root==NULL)
       {
           return 0;
       }
       if(!root->left&&!root->right)
       {
           return 1;
       }
 return 1+max(depth(root->left),depth(root->right));
   }
 
    bool isBalanced(TreeNode* root) {
//递归出口
if(root==NULL)
{
    return true;
}
if(!root->left&&!root->right)
{
    return true;
}
//递归体
return isBalanced(root->left)&&isBalanced(root->right)&&abs(depth(root->left)-depth(root->right))<=1;
    }
};
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
二叉树的镜像

算法复习:二叉树合集翻转二叉树二叉树的序列化和反序列化(剑指 Offer 37)LeetCode 654 最大二叉树二叉树的所有_子树_03

递归:

如果二叉树为空,返回空

如果二叉树为叶子节点,返回叶子节点

递归反转左子树和右子树

改变根节点的指向

public TreeNode Mirror (TreeNode pRoot) {
        // write code here
        if(pRoot==null)return null;
        if(pRoot!=null&&pRoot.left==null&&pRoot.right==null)return pRoot;
        TreeNode l=Mirror(pRoot.left);
        TreeNode r=Mirror(pRoot.right);
        pRoot.left=r;
        pRoot.right=l;
        return pRoot;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
LeetCode1161 最大层内元素和 

返回一层中和最大的层号,如果有多个最大和,返回最小层数

class Solution {
public:
    int maxLevelSum(TreeNode* root) {
          queue<TreeNode *>q;
          q.push(root);
          int max_sum=INT_MIN;
          int sum;
          int min_level=0;
          int level=0;
          while(!q.empty()){
              int size=q.size();
              sum=0;
              level++;
              for(int i=0;i<size;i++){
              TreeNode * cur=q.front();
              q.pop();
              sum+=cur->val;
              if(cur->left)q.push(cur->left);
              if(cur->right)q.push(cur->right);
              }
              if(sum>max_sum){
                  max_sum=sum;
                  min_level=level;
              }
              
          }
          
          return min_level;
    }
};
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
二叉树求到某一个节点路径

算法复习:二叉树合集翻转二叉树二叉树的序列化和反序列化(剑指 Offer 37)LeetCode 654 最大二叉树二叉树的所有_子树_04

递归出口:当根节点为空时,返回空数组。

当根节点不为空,如果根节点值为val,返回只有根节点的数组。当只有根节点,且根节点值不为val,返回空数组。

递归体:递归求出左子树到val的路径,递归求出右子树到val的路径,在路径前加入根节点。

vector<TreeNode*>l=path(root->left,val);
vector<TreeNode*>r=path(root->right,val);
if(l.size()!=0)
{
  vector<TreeNode*>res;
res.push_back(root);
res.insert(res.end(),l.begin(),l.end());
return res;
}
 if (r.size() != 0)
{
   vector<TreeNode*>res;
   res.push_back(root);
   res.insert(res.end(), r.begin(), r.end());
   return res;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
LeetCode513 找左下角的值

层序遍历最后一层第一个值

int findBottomLeftValue(TreeNode* root) {
      vector<int>level;
      queue<TreeNode*>que;
      if(root) que.push(root);
      while(!que.empty()){   
           int size=que.size();
           level.clear();
           for(int i=0;i<size;i++){
              TreeNode *cur=que.front();
              que.pop();
              level.push_back(cur->val);
              if(cur->left)que.push(cur->left);
              if(cur->right)que.push(cur->right); 
     return level[0];
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
LeetCode 543 二叉树的直径

给你一棵二叉树的根节点,返回该树的直径。二叉树的直径是指树中任意两个节点之间最长路径的长度.这条路径可能经过也可能不经过根节点root。两节点之间路径的长度由它们之间边数表示。

算法复习:二叉树合集翻转二叉树二叉树的序列化和反序列化(剑指 Offer 37)LeetCode 654 最大二叉树二叉树的所有_子树_05

int res=0;
    int h(TreeNode*root){
        if(root==nullptr)return 0;
        if(!root->left&&!root->right)return 1;
        return 1+max(h(root->left),h(root->right));
    }
    int length(TreeNode *root){
        return h(root->right)+h(root->left);
    }
    int diameterOfBinaryTree(TreeNode* root) {
        if(!root)return 0;
        res=max(res,length(root));
        diameterOfBinaryTree(root->left);
        diameterOfBinaryTree(root->right);
        return res;
    }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
LeetCode113 路径总和

算法复习:二叉树合集翻转二叉树二叉树的序列化和反序列化(剑指 Offer 37)LeetCode 654 最大二叉树二叉树的所有_数据结构_06

注意:

(1)if(sum>target)不能作为剪枝的条件,因为数可能是负数,所以会越加越小。

(2)不能使用root为空作为递归的出口,因为叶子节点会走两次到空节点,结果会重复。

算法复习:二叉树合集翻转二叉树二叉树的序列化和反序列化(剑指 Offer 37)LeetCode 654 最大二叉树二叉树的所有_数据结构_07

class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        int n=matrix.size();
        int m=matrix[0].size();
        for(int i=0;i<n;i++){
            int l=0;
            int r=m-1;
            while(l<r){
                int mid=l+(r-l)/2;
                if(matrix[i][mid]>=target)r=mid;
                else l=mid+1;
            }
            if(matrix[i][r]==target)return true;
        }   
        return false;
    }
};
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
LeetCode 662 二叉数的最大宽度

给你一棵二叉树的根节点 root,返回树的 最大宽度。树的最大宽度是所有层中最大的 宽度 。

每一层的 宽度 被定义为该层最左和最右的非空节点(即,两个端点)之间的长度。将这个二叉树视作与满二叉树结构相同,两端点间会出现一些延伸到这一层的 null 节点,这些 null 节点也计入长度。题目数据保证答案将会在32 位带符号整数范围内。

算法复习:二叉树合集翻转二叉树二叉树的序列化和反序列化(剑指 Offer 37)LeetCode 654 最大二叉树二叉树的所有_子树_08

二叉树的序列化和反序列化(剑指offer)

二叉树的序列化

算法复习:二叉树合集翻转二叉树二叉树的序列化和反序列化(剑指 Offer 37)LeetCode 654 最大二叉树二叉树的所有_数据结构_09

 方法:先序遍历这颗二叉树,遇到空子树的时候序列化成 None,否则继续递归序列化

void rserialize(TreeNode *root,string &str){
  if(root==NULL)str+="None,";
  else{
      str+=to_string(root->val)+",";
      rserialize(root->left,str);
      rserialize(root->right,str);
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.

二叉树的反序列化

算法复习:二叉树合集翻转二叉树二叉树的序列化和反序列化(剑指 Offer 37)LeetCode 654 最大二叉树二叉树的所有_算法_10

算法复习:二叉树合集翻转二叉树二叉树的序列化和反序列化(剑指 Offer 37)LeetCode 654 最大二叉树二叉树的所有_子树_11

//根据链表建树
TreeNode* rdeserialize(list<string>& dataArray) {
        if (dataArray.front() == "None") {
            dataArray.erase(dataArray.begin());
            return nullptr;
        }//如果链表为空,则返回空树
        TreeNode* root = new TreeNode(stoi(dataArray.front()));
        dataArray.erase(dataArray.begin());//根节点
        root->left = rdeserialize(dataArray);//左子树
        root->right = rdeserialize(dataArray);//右子树
        return root;
}
//反序列化
    TreeNode* deserialize(string data) {
        list<string> dataArray;
        string str;
        //把二叉树节点序列化的值加入链表
        for (auto& ch : data) {
            if (ch == ',') {
                dataArray.push_back(str);
                str.clear();
            } else {
                str.push_back(ch);
            }
        }
        return rdeserialize(dataArray);
  }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.