All questions are simple level.

Construct String from Binary Tree

Question[606]:You need to construct a string consists of parenthesis and integers from a binary tree with the preorder traversing way. The null node needs to be represented by empty parenthesis pair "()". And you need to omit all the empty parenthesis pairs that don't affect the one-to-one mapping relationship between the string and the original binary tree.

Example

Input: Binary tree: [1,2,3,4]
1
/ \
2 3
/
4
Output: "1(2(4))(3)"
Explanation: Originallay it needs to be "1(2(4)())(3()())", but you need to omit all the unnecessary empty parenthesis pairs. And it will be "1(2(4))(3)".

Solution

Use pre-order traversal. These two methods is the same. The first one is implemented by passing arguments by reference. The second one is implemented by returned value.

class Solution
{
public:
string tree2str(TreeNode *t)
{
// string s = "";
// preorder(t, s);
// return s;
return preorder2(t);
} void preorder(TreeNode *p, string &s)
{
if (p == nullptr)
return;
string sval = to_string(p->val);
string l, r;
preorder(p->left, l);
preorder(p->right, r);
s += sval;
bool lflag = (l != "");
bool rflag = (r != "");
if (lflag && rflag)
s += "(" + l + ")(" + r + ")";
if (!lflag && rflag)
s += "()(" + r + ")";
if (lflag && !rflag)
s += "(" + l + ")";
} string preorder2(TreeNode *p)
{
if (p == nullptr)
return "";
bool l = (p->left != nullptr);
bool r = (p->right != nullptr);
string sval = to_string(p->val);
if (l && r)
return sval + "(" + preorder2(p->left) + ")(" + preorder2(p->right) + ")";
if (!l && r)
return sval + "()(" + preorder2(p->right) + ")";
if (l && !r)
return sval + "(" + preorder2(p->left) + ")";
return sval;
}
};

Merge Two Binary Trees

Question[617]: Given two binary trees and imagine that when you put one of them to cover the other, some nodes of the two trees are overlapped while the others are not. You need to merge them into a new binary tree. The merge rule is that if two nodes overlap, then sum node values up as the new value of the merged node. Otherwise, the NOT null node will be used as the node of new tree.

Solution: Two versions, including recursion and iteration.

  • Recursion version-1: create a completely new tree

    class Solution
    {
    public:
    TreeNode *mergeTrees(TreeNode *t1, TreeNode *t2)
    {
    TreeNode *root = nullptr;
    innerMerge(root, t1, t2);
    return root;
    }
    void innerMerge(TreeNode *&p, TreeNode *t1, TreeNode *t2)
    {
    bool flag1 = (t1 != nullptr);
    bool flag2 = (t2 != nullptr);
    if (flag1 && flag2)
    p = new TreeNode(t1->val + t2->val);
    else if (!flag1 && flag2)
    p = new TreeNode(t2->val);
    else if (flag1 && !flag2)
    p = new TreeNode(t1->val);
    else
    return;
    innerMerge(p->left, flag1 ? t1->left : nullptr, flag2 ? t2->left : nullptr);
    innerMerge(p->right, flag1 ? t1->right : nullptr, flag2 ? t2->right : nullptr);
    }
    };
  • Recursion version-2: directly modify on t1

    class Solution
    {
    public:
    TreeNode *mergeTrees(TreeNode *t1, TreeNode *t2)
    {
    return innerMerge(t1, t2);
    } TreeNode *innerMerge(TreeNode *t1, TreeNode *t2)
    {
    if (t1 == nullptr)
    return t2;
    if (t2 == nullptr)
    return t1;
    t1->val += t2->val;
    t1->left = innerMerge(t1->left, t2->left);
    t1->right = innerMerge(t1->right, t2->right);
    return t1;
    }
    };
  • Iteration-version implemented by pre-order traversal, modify on t1 :

    TreeNode *mergeTrees(TreeNode *t1, TreeNode *t2)
    {
    return preorderMerge(t1, t2);
    }
    TreeNode *preorderMerge(TreeNode *t1, TreeNode *t2)
    {
    typedef pair<TreeNode *, TreeNode *> node;
    if (t1 == nullptr)
    return t2;
    stack<node> s;
    s.push(node(t1, t2));
    while (!s.empty())
    {
    node n = s.top();
    s.pop();
    if (n.second == nullptr)
    continue;
    n.first->val += n.second->val;
    if (n.first->left == nullptr)
    n.first->left = n.second->left;
    else
    s.push(node(n.first->left, n.second->left));
    if (n.first->right == nullptr)
    n.first->right = n.second->right;
    else
    s.push(node(n.first->right, n.second->right));
    }
    return t1;
    }

Average of Levels in Binary Tree

Question[637]: Given a non-empty binary tree, return the average value of the nodes on each level in the form of an array.

Example

Input:
3
/ \
9 20
/ \
15 7
Output: [3, 14.5, 11]
Explanation: The average value of nodes on level 0 is 3, on level 1 is 14.5, and on level 2 is 11. Hence return [3, 14.5, 11].

Solution

  • Level-order traversal. Use the map sumrecord to record the sum of each level. Use numrecord to record the number of nodes of each level.

    vector<double> averageOfLevels(TreeNode *root)
    {
    typedef pair<TreeNode *, int> node;
    unordered_map<int, double> sumrecord;
    unordered_map<int, int> numrecord;
    queue<node> q;
    q.push(node(root, 0));
    while (!q.empty())
    {
    auto n = q.front();
    q.pop();
    sumrecord[n.second] += n.first->val;
    numrecord[n.second]++;
    if (n.first->left != nullptr)
    q.push(node(n.first->left, n.second + 1));
    if (n.first->right != nullptr)
    q.push(node(n.first->right, n.second + 1));
    }
    vector<double> v(numrecord.size());
    for (auto &x : sumrecord)
    v[x.first] = x.second / numrecord[x.first];
    return v;
    }
  • Level-order traversal. Only use queue, discard the help of node and unordered_map.

    vector<double> levelorder(TreeNode *root)
    {
    vector<double> v;
    queue<TreeNode *> q;
    q.push(root);
    while (!q.empty())
    {
    queue<TreeNode *> nextlevel;
    int64_t sum = 0;
    int counter = 0;
    while (!q.empty())
    {
    auto p = q.front();
    q.pop();
    sum += p->val, counter++;
    if (p->left != nullptr)
    nextlevel.push(p->left);
    if (p->right != nullptr)
    nextlevel.push(p->right);
    }
    q = nextlevel;
    v.push_back(sum * 1.0 / counter);
    }
    return v;
    }

Two Sum IV - Input is a BST

Question[653]: Given a Binary Search Tree and a target number, return true if there exist two elements in the BST such that their sum is equal to the given target.

Example

Input:
5
/ \
3 6
/ \ \
2 4 7
Target = 9
Output: True
Explanation: 9 = 3+6, 9 = 2+7, 9 = 4+5

Solution

First, implement a function named search(root, val) which is used to search val in a tree root. Then, traversal the tree root to judge every node p whether there is another node q satisfies p->val + q->val == k.

bool search(TreeNode *p, int val, TreeNode *exceptNode)
{
if (p == nullptr)
return false;
if (p->val == val && p != exceptNode)
return true;
if (val < p->val)
return search(p->left, val, exceptNode);
return search(p->right, val, exceptNode);
}
bool levelorder(TreeNode *root, int k)
{
queue<TreeNode *> q;
q.push(root);
while (!q.empty())
{
auto p = q.front();
q.pop();
int val = k - p->val;
if (search(root, val, p))
return true;
if (p->left != nullptr)
q.push(p->left);
if (p->right != nullptr)
q.push(p->right);
}
return false;
}

Trim a Binary Search Tree

Question[669]: 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.

Example-1

Input-1:
1
/ \
0 2
L = 1
R = 2
Output-1:
1
\
2

Example-2

Input-2:
3
/ \
0 4
\
2
/
1
L = 1
R = 3
Output-2:
3
/
2
/
1

Solution

For each node of a BST, there are only three cases:

  1. val < L
  2. val > R
  3. L <= val <= R

When val < L, for an example:

   parent            parent          parent
| | |
9 ==> 9 ==> right
/ \ / \
left right null right

All values in the left sub-tree should be less than 9, hence the left sub-tree should be discarded. And because of '9' is less than L, hence it also should be discarded. The code to do these two operations is:

p->left = nullptr, p = trim(p->right)

The case val > R is similar to case val < L.

For the case L <= val <= R, there is nothing to do on the val node. Just continue to trim on its left sub-tree and right sub-tree.

Version-1:

TreeNode *trimBST(TreeNode *root, int L, int R)
{
return innerTrim(root, L, R);
}
TreeNode *innerTrim(TreeNode *&p, int l, int r)
{
if (p == nullptr)
return nullptr;
if (p->val < l)
{
p->left = nullptr;
return p = innerTrim(p->right, l, r);
}
else if (p->val > r)
{
p->right = nullptr;
return p = innerTrim(p->left, l, r);
}
else
{
p->left = innerTrim(p->left, l, r);
p->right = innerTrim(p->right, l, r);
return p;
}
}

Version-2:

TreeNode *trimBST(TreeNode *root, int L, int R)
{
innerTrim2(root, L, R);
return root;
}
void innerTrim2(TreeNode *&p, int l, int r)
{
if (p == nullptr)
return;
if (p->val < l)
{
p->left = nullptr, p = p->right;
innerTrim2(p, l, r);
return;
}
else if (p->val > r)
{
p->right = nullptr, p = p->left;
innerTrim2(p, l, r);
return;
}
else
{
innerTrim2(p->left, l, r);
innerTrim2(p->right, l, r);
}
}

Second Minimum Node In a Binary Tree

Question[671]: Given a non-empty special binary tree consisting of nodes with the non-negative value, where each node in this tree has exactly two or zero sub-node. If the node has two sub-nodes, then this node's value is the smaller value among its two sub-nodes. More formally, the property root.val = min(root.left.val, root.right.val) always holds. Given such a binary tree, you need to output the second minimum value in the set made of all the nodes' value in the whole tree. If no such second minimum value exists, output -1 instead.

Example-1

Input:
2
/ \
2 5
/ \
5 7 Output: 5
Explanation: The smallest value is 2, the second smallest value is 5.

Solution

The smallest value in the tree is root->val (at level-0) . Hence the solution is to find the smallest value in all numbers greater (at level >= 1) than root->val.

class Solution
{
public:
int findSecondMinimumValue(TreeNode *root)
{
if (root == nullptr || root->left == nullptr)
return -1;
int minval = root->val;
int result = -1;
queue<TreeNode *> q;
auto p = root;
q.push(p);
while (!q.empty())
{
p = q.front();
q.pop();
if (p->val > minval)
result = result == -1 ? p->val : min(result, p->val);
if (p->left)
q.push(p->left);
if (p->right)
q.push(p->right);
}
return result;
}
};

Search in a Binary Search Tree

Question[700]: Given the root node of a binary search tree (BST) and a value. You need to find the node in the BST that the node's value equals the given value. Return the subtree rooted with that node. If such node doesn't exist, you should return NULL.

Example

Given the tree:
4
/ \
2 7
/ \
1 3
And the value to search: 2
2
/ \
1 3

Solution

Simple question!

class Solution
{
public:
TreeNode *searchBST(TreeNode *root, int val)
{
return iterationSearch(root, val);
}
TreeNode *recursionSearch(TreeNode *p, int val)
{
if (p == nullptr)
return nullptr;
if (p->val == val)
return p;
else if (val < p->val)
return recursionSearch(p->left, val);
else
return recursionSearch(p->right, val);
}
TreeNode *iterationSearch(TreeNode *root, int val)
{
auto p = root;
while (p != nullptr)
{
if (p->val == val)
return p;
else if (val < p->val)
p = p->left;
else
p = p->right;
}
return nullptr;
}
};

N-ary Tree

Maximum Depth of N-ary Tree

Question[559]: Given a n-ary tree, find its maximum depth. The maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node. Nary-Tree input serialization is represented in their level order traversal, each group of children is separated by the null value (See examples).

Example

Input: root = [1,null,3,2,4,null,5,6]
1
/ | \
3 2 4
/ \
5 6
Output: 3

Solution

Level order traversal.

#include "leetcode.h"
#include <queue>
class Node
{
public:
int val;
vector<Node *> children;
Node() {}
Node(int _val) { val = _val; }
Node(int _val, vector<Node *> _children)
{
val = _val;
children = _children;
}
};
class Solution
{
public:
int maxDepth(Node *root)
{
return levelorder(root);
}
int levelorder(Node *root)
{
auto p = root;
queue<Node *> q;
q.push(p);
int level = 1;
while (!q.empty())
{
queue<Node *> nextlevel;
while (!q.empty())
{
p = q.front(), q.pop();
for (auto x : p->children)
nextlevel.push(x);
}
level += (!nextlevel.empty());
q = nextlevel;
}
return level;
}
};

N-ary Tree Preorder Traversal

Question[589]: Given an n-ary tree, return the preorder traversal of its nodes' values.

Example

Input: root = [1,null,3,2,4,null,5,6]
1
/ | \
3 2 4
/ \
5 6
Output: [1,3,5,6,2,4]

Solution

First step, we should have a look at perorder traversal of a binary tree, which is similar to open the door of fridge.

stack s;
s.push(root);
while (!s.empty())
{
p = s.top(), s.pop();
print(p->val);
if (p->right) s.push(p->right);
if (p->left) s.push(p->left);
}

Second, put the elephant

[leetcode] 树(Ⅱ)的更多相关文章

  1. LeetCode树专题

    LeetCode树专题 98. 验证二叉搜索树 二叉搜索树,每个结点的值都有一个范围 /** * Definition for a binary tree node. * struct TreeNod ...

  2. leetcode 树类型题

    树的测试框架: // leetcodeTree.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <iostream& ...

  3. leetcode: 树

    1. sum-root-to-leaf-numbers Given a binary tree containing digits from0-9only, each root-to-leaf pat ...

  4. [leetcode] 树 -Ⅰ

    均为 Simple 难度的水题. 二叉树的中序遍历 题目[94]:给定一个二叉树,返回它的中序 遍历. 解题思路:Too simple. class Solution { public: vector ...

  5. Leetcode 树(102, 637)

    637: 二叉树的层平均值 给定一个非空二叉树,返回一个由每层节点平均值组成的数组: https://leetcode-cn.com/problems/average-of-levels-in-bin ...

  6. leetcode树专题894.897,919,951

    满二叉树是一类二叉树,其中每个结点恰好有 0 或 2 个子结点. 返回包含 N 个结点的所有可能满二叉树的列表. 答案的每个元素都是一个可能树的根结点. 答案中每个树的每个结点都必须有 node.va ...

  7. leetcode 树的锯齿形状遍历

    二叉树的锯齿形层次遍历     给定一个二叉树,返回其节点值的锯齿形层次遍历.(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行). 例如:给定二叉树 [3,9,20,null,n ...

  8. Leetcode 树 Populating Next Right Pointers in Each Node II

    本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie Populating Next Right Pointers in Each Node II ...

  9. leetcode树相关

    目录 144前序遍历 94中序遍历(98验证二叉搜索树.230二叉搜索树中第K小的元素) 145后序遍历 102/107层次遍历(104二叉树最大深度.103 105从前序与中序遍历序列构造二叉树 1 ...

随机推荐

  1. 一起了解 .Net Foundation 项目 No.14

    .Net 基金会中包含有很多优秀的项目,今天就和笔者一起了解一下其中的一些优秀作品吧. 中文介绍 中文介绍内容翻译自英文介绍,主要采用意译.如与原文存在出入,请以原文为准. .NET Core .NE ...

  2. 分享一个基于Net Core 3.1开发的模块化的项目

    先简单介绍下项目(由于重新基于模块化设计了整个项目,所以目前整个项目功能不多) 1.Asp.Net Core 3.1.2+MSSQL2019(LINUX版) 2.中间件涉及Redis.RabbitMQ ...

  3. 谈谈集合.Queue

    之前说到,Java中集合的主要作用就是装盛其他数据和实现常见的数据结构.所以当我们要用到"栈"."队列"."链表"和"数组&quo ...

  4. 基于sklearn的metrics库的常用有监督模型评估指标学习

    一.分类评估指标 准确率(最直白的指标)缺点:受采样影响极大,比如100个样本中有99个为正例,所以即使模型很无脑地预测全部样本为正例,依然有99%的正确率适用范围:二分类(准确率):二分类.多分类( ...

  5. 纯C 实现 strpos substr strspilt str_trim

    在C 语言中没有C++ 好用的 spilt 方法 (STL 带的也不怎么好用) #include <stdio.h> #include <string.h> #include ...

  6. 软件基础1Word文档编辑

    word文档编辑 启动Word2010 创建文档,<你好word>. 编辑文字. 保存的三种方式. ctrl+s. 点击文件选择保存,或另存为. 快速工具栏保存按钮. 设置字体 1.通过工 ...

  7. 19.10.11学习日记随笔 mysql事务隔离性

    一天的感悟 学习事务的处理方式,其中反想自己学过的flask 默认是开启事务的,flask_sqlalchemy每次在提交时都是需要commit,或者失败是需要rollback回滚操作的,其实pyth ...

  8. python_字符串&列表&元组&字典之间转换学习

    #!/usr/bin/env/python #-*-coding:utf-8-*- #Author:LingChongShi #查看源码Ctrl+左键 #数据类型之间的转换 Str='www.baid ...

  9. 谈谈MySQL数据库索引

    在分析MySQL数据库索引之前,很多小伙伴对数据结构中的树理解不够深刻.因此我们由浅入深一步步探讨树的演进过程,再一步步引出MySQL数据库索引底层数据结构. 一.二叉树 二叉查找树也称为有序二叉查找 ...

  10. go源码分析(三) 使用go http包开发web时遇到的坑之卸载插件,重启插件管理,仍然可以访问已经卸载的插件

    问题描述: web页面下发重启指令后,对卸载插件的处理不完整(虽然列表已经没有插件描述,但是在HandleFunc的路由列表中依然存在) 我们需要清空路由列表map 路由列表结构见代码: net/ht ...