二叉树专题

来源:互联网 发布:马云是如何开创淘宝的 编辑:程序博客网 时间:2024/06/11 03:25

声明:部分试题、解决方案来自LeetCode,本文旨在学习

二叉树的非递归先序、中序、后序遍历在栈和队列专题

1.Symmetric Tree

Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center).

For example, this binary tree [1,2,2,3,4,4,3] is symmetric:

    1   / \  2   2 / \ / \3  4 4  3

But the following [1,2,2,null,3,null,3] is not:

    1   / \  2   2   \   \   3    3

Solution:

递归,时间复杂度O(n),空间复杂度O(logn)

bool isSymmetric(TreeNode* root){    return root ? isSymmetric(root->left,root->right) : true;}bool isSymmetric(TreeNode* left, TreeNode* right){    //终止条件    if(!left && !right)         return true;    //终止条件    if(!left || !right)        return false;    //三方合并    return left->val == right->val && isSymmetric(left->left,right->right) && isSymmetric(left->right,right->left);}

2.Flatten Binary Tree to Linked List

Given a binary tree, flatten it to a linked list in-place.

For example,
Given

         1        / \       2   5      / \   \     3   4   6

The flattened tree should look like:

   1    \     2      \       3        \         4          \           5            \             6

Solution:

递归,时间复杂度O(n),空间复杂度O(logn)

void flatten(TreeNode* root){    if(root == NULL)        return;    flatten(root->left);    flatten(root->right);    if(root->left == NULL)        return;    //寻找左链表最后一个节点    TreeNode* p = root->left;    while(p->right)        p = p->right;    //三方合并,将左子树所形成的链表插入到root和root->right之间    p->right = root->right;    root->right = root->left;    root->left = NULL;}

3.Construct Binary Tree from Preorder and Inorder Traversal

Given preorder and inorder traversal of a tree, construct the binary tree.

Note:
You may assume that duplicates do not exist in the tree.

Solution:

仔细分析先序遍历、中序遍历的特征即可

递归,时间复杂度O(n),空间复杂度O(logn)

TreeNode* buildTree(vector<int>& preOrder, vector<int>& inOrder){    return buildTree(begin(preOrder),end(preOrder),begin(inOrder),end(inOrder));}template<typename T>TreeNode* buildTree(T pre_first, T pre_last, T in_first, T in_last){    if(pre_first == pre_last)        return NULL;    if(in_first == in_last)        return NULL;    TreeNode* root = new TreeNode(*pre_first);    auto inRootPos = find(in_first,in_last,*pre_first);    auto leftSize = distance(in_first,inRootPos);    root->left = buildTree(next(pre_first),next(pre_first,leftSize+1),in_first,next(in_first,leftSize));    root->right = buildTree(next(pre_first,leftSize+1),pre_last,next(inRootPos),in_last);    return root;}

4.Construct Binary Tree from Inorder and Postorder Traversal

Given inorder and postorder traversal of a tree, construct the binary tree.

Note:
You may assume that duplicates do not exist in the tree.

Solution:

仔细分析中序遍历、后序遍历的特征即可

递归,时间复杂度O(n),空间复杂度O(logn)

TreeNode* buildTree(vector<int>& inOrder, vector<int>& postOrder){    return buildTree(begin(inOrder),end(inOrder),begin(postOrder),end(postOrder));}template<typename T>TreeNode* buildTree(T in_first, T in_last, T post_first, T post_last){    if(in_first == in_last)        return NULL;    if(post_first == post_last)        return NULL;    const auto val = *prev(post_last);    TreeNode* root = new TreeNode(val);    auto inRootPos = find(in_first,in_last,val);    auto leftSize = distance(in_first,inRootPos);    root->left = buildTree(in_first,inRootPos,post_first,next(post_first,leftSize));    root->right = buildTree(next(inRootPos),in_last,next(post_first,leftSize),prev(post_last));    return root;}

5.Unique Binary Search Trees II

Given an integer n, generate all structurally unique BST’s (binary search trees) that store values 1…n.

For example,
Given n = 3, your program should return all 5 unique BST’s shown below.

   1         3     3      2      1    \       /     /      / \      \     3     2     1      1   3      2    /     /       \                 \   2     1         2                 3

Solution:

vector<TreeNode*> generate(int start, int end){    vector<TreeNode*> subTree;    if (start > end)    {        subTree.push_back(NULL);        return subTree;    }     for (int k = start; k <= end; k++)    {        vector<TreeNode*> leftSubs = generate(start,k-1);        vector<TreeNode*> rightSubs = generate(k+1,end);        for (int i = 0; i < leftSubs.size(); i++)        {            for (int j = 0; j < rightSubs.size(); j++)            {                TreeNode* node = new TreeNode(k);                node->left = leftSubs[i];                node->right = rightSubs[j];                subTree.push_back(node);            }        }    }    return subTree;}vector<TreeNode*> generateTrees(int n){    if(n == 0)        return generate(1,0);    return generate(1,n);}

6.Convert Sorted List to Binary Search Tree

Given a singly linked list where elements are sorted in ascending order, convert it to a height balanced BST.

Solution:

自底向上,时间复杂度O(n),空间复杂度O(logn)

TreeNode* sortedListToBSTCore(ListNode*& list,int start, int end){    if(start > end)        return NULL;    int mid = start + (end - start)/2;    TreeNode* leftChild = sortedListToBSTCore(list, start, mid-1);    TreeNode* parent = new TreeNode(list->val);    parent->left = leftChild;    list = list->next;    TreeNode* rightChild = sortedListToBSTCore(list, mid+1, end);    return parent;}TreeNode* sortedListToBST(ListNode* head){    int len = 0;    ListNode* p = head;    while (p)    {        len++;        p = p->next;    }    return sortedListToBSTCore(head,0,len-1);}

7.二叉树最小深度

int minDepth(TreeNode* root){    if(root == NULL)        return 0;    if(root->left == NULL)        return 1 + minDepth(root->right);    if(root->right == NULL)        return 1 + minDepth(root->left);    return 1 + min(minDepth(root->left),minDepth(root->right));}

8.二叉树最大深度

int maxDepth(TreeNode* root){    if(root == NULL)        return 0;    return 1 + max(maxDepth(root->left), maxDepth(root->right));}

9.根据层序遍历序列重建二叉树

这一部分主要利用了层序遍历的树形结构性质以及队列这一数据结构

Node* get_tree(vector<int> vec){    int vec_size = vec.size();    if(vec_size == 0)        return NULL;    Node* l;    Node* r;    Node* root;    Node* node;    bool has_left = false;    bool has_right = false;    queue<Node*> q;    for(int i = 0; i < vec_size; i++)    {        //左子树        if(2*i+1 < vec_size)            l = new Node(vec[2*i+1]);        else            l = NULL;        //右子树        if(2*i+2 < vec_size)            r = new Node(vec[2*i+2]);        else            r = NULL;        node = new Node(vec[i],l,r);        if(i == 0)        {            root = node;        }        else if(i%2 == 1)        {            Node* tmp = q.front();            tmp->left = node;            has_left = true;        }        else        {            Node* tmp = q.front();            tmp->right = node;            has_right = true;        }        //判断左右子树是否都建立联系        if(has_left && has_right)        {            has_left = false;            has_right = false;            q.pop();        }        q.push(node);    }    return root;}

10.查询路径和

这一部分是基于深度优先的一个递归实现,实现思路在二叉树这块值得学习。

void find_path(Node* root,vector<int> &vec,int &sum,int &cur_sum){    vec.push_back(root->val);    cur_sum += root->val;    if(root->left == NULL && root->right == NULL && sum == cur_sum)    {        output_vector(vec);    }    if(root->left != NULL)        find_path(root->left,vec,sum,cur_sum);    if(root->right != NULL)        find_path(root->right,vec,sum,cur_sum);    vec.pop_back();    cur_sum -= root->val;}

11.Sum Root to Leaf Numbers

Given a binary tree containing digits from 0-9 only, each root-to-leaf path could represent a number.

An example is the root-to-leaf path 1->2->3 which represents the number 123.

Find the total sum of all root-to-leaf numbers.

For example,

    1   / \  2   3

The root-to-leaf path 1->2 represents the number 12.
The root-to-leaf path 1->3 represents the number 13.

Return the sum = 12 + 13 = 25.

Solution:

时间复杂度O(n),空间复杂度O(logn)

int dfs(TreeNode* root, int sum){    if(root == NULL)        return 0;    int num = sum*10+root->val;    if(root->left == NULL && root->right == NULL)        return num;    return dfs(root->left, num) + dfs(root->right, num);}int sumNumbers(TreeNode* root){    return dfs(root,0);}
0 0
原创粉丝点击