leetcode解题思路分析(十六)106 - 112题

  1. 从中序与后序遍历序列构造二叉树
    根据一棵树的中序遍历与后序遍历构造二叉树。

和上一题基本一致,这里注意两点:后序遍历根节点永远在最后,后序遍历从后往前是先右子树后左子树,由此可得解

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode *buildTree(vector<int>& inorder, vector<int>& postorder) {
        int pos = postorder.size() - 1;
        return buildTree(postorder, pos, inorder, 0, inorder.size() - 1);
    }

    TreeNode *buildTree(vector<int>& postorder, int& pos, vector<int>& inorder, int left, int right) 
    {
        if (pos >= postorder.size()) 
            return 0;

        int i = left;

        // 搜索到目前的根在中序的位置i
        for (; i <= right; ++i) 
        {
            if (inorder[i] == postorder[pos]) 
                break;
        }

        // 当前的根为前序的pos
        TreeNode* node = new TreeNode(postorder[pos]);

        // 当右边只剩一个就不用递归了
        if (i + 1 <= right) 
            node->right = buildTree(postorder, --pos, inorder, i + 1, right);  // 右子树

        // 当左边只剩一个就不用递归了
        if (left <= i - 1) 
            node->left = buildTree(postorder, --pos, inorder, left, i - 1);  // 左子树

        return node;
    }

};
  1. 二叉树的层次遍历2
    给定一个二叉树,返回其节点值自底向上的层次遍历。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)

和之前的并无区别,最后对vector进行反转即可

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
    vector<vector<int>> ret;
public:
    vector<vector<int>> levelOrderBottom(TreeNode* root) {
        search(root, 0);
        reverse(ret.begin(), ret.end());
        return ret;
    }

    void search(TreeNode *root, int height)
    {
        if (root == NULL)
            return;
        
        if (height == ret.size())
            ret.resize(height + 1);

        ret[height].push_back(root->val);
        height++;
        search(root->left, height);
        search(root->right, height);
    }
};
  1. 将有序数组转换为二叉搜索树
    本题解法不唯一,在此采用的策略是去中间点为根,左边为左子树右边为右子树
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode *sortedArrayToBST(vector<int>& nums) {
        return makeTree(nums, 0, nums.size());
    }

    TreeNode *makeTree(vector<int> &nums, int left, int right)
    {
        if (left == right)
            return NULL;
        
        int mid = (left + right) / 2;

        TreeNode *root = new TreeNode(nums[mid]);
        root->left = makeTree(nums, left, mid);
        root->right = makeTree(nums, mid + 1, right);

        return root;
    }
};
  1. 有序链表转二叉搜索树
    给定一个单链表,其中的元素按升序排序,将其转换为高度平衡的二叉搜索树。
    本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。

本题和上题的区别在于链表不方便索引。这里有两种方法:一种是采取快慢指针每次找到中间节点,另一种是将链表转存在数组中。是要空间还是时间就看需求了

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */

class Solution {
public:
    TreeNode* sortedListToBST(ListNode* head) {
        return buildTree(head, nullptr);
    }
    TreeNode * buildTree(ListNode* head, ListNode * tail){
        if(head == tail) return nullptr;
        ListNode* slow = head, *fast = head;
        while(fast != tail && fast->next != tail){
            slow = slow->next;
            fast = fast->next->next;
        }
        TreeNode * root = new TreeNode(slow->val);
        root->left = buildTree(head, slow);
        root->right = buildTree(slow->next, tail);
        return root;
    }
};

class Solution {
public:
    TreeNode* sortedListToBST(ListNode* head) {
        vector<int> v;
        while(head != nullptr){
            v.push_back(head->val);
            head = head->next;
        }
        return buildTree(v, 0, v.size());
    }
    TreeNode * buildTree(vector<int> & v, int begin, int end){
        if(begin == end) return nullptr;
        int middle = (begin+end)/2;
        TreeNode * root = new TreeNode(v[middle]);
        root->left = buildTree(v, begin, middle);
        root->right = buildTree(v, middle+1, end);
        return root;
    }
};


  1. 平衡二叉树
    给定一个二叉树,判断它是否是高度平衡的二叉树。

一个平衡二叉树要求所有子树均为平衡二叉树,所以我们可以利用递归检测每一个子树是否满足要求,有一个不满足则为假。具体到实现有两种选择:第一种是自顶向下,比较当前情况然后再检查子树是否满足,第二种是自底向上,先去递归到最小子树看是否满足,再依次往上比较

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
private:
  // Recursively obtain the height of a tree. An empty tree has -1 height
  int height(TreeNode* root) { 
    // An empty tree has height -1
    if (root == NULL) {
      return -1;
    }
    return 1 + max(height(root->left), height(root->right));
  }
public:
  bool isBalanced(TreeNode* root) {
    // An empty tree satisfies the definition of a balanced tree
    if (root == NULL) {
      return true;
    }

    // Check if subtrees have height within 1. If they do, check if the
    // subtrees are balanced
    return abs(height(root->left) - height(root->right)) < 2 &&
      isBalanced(root->left) &&
      isBalanced(root->right);
  }
};


class Solution {
private:
  // Return whether or not the tree at root is balanced while also storing
  // the tree's height in a reference variable. 
  bool isBalancedTreeHelper(TreeNode* root, int& height) {
    // An empty tree is balanced and has height = -1
    if (root == NULL) {
      height = -1;
      return true;
    }

    // Check subtrees to see if they are balanced. If they are, check if the 
    // current node is also balanced using the heights obtained from the 
    // recursive calls.
    int left, right;
    if (isBalancedTreeHelper(root->left, left)  &&
        isBalancedTreeHelper(root->right, right) &&
        abs(left - right) < 2) {
      // Store the current tree's height
      height = max(left, right) + 1;
      return true;
    }
    return false;
  }
public:
  bool isBalanced(TreeNode* root) {
    int height;
    return isBalancedTreeHelper(root, height);
  }
};


  1. 二叉树的最小深度
    给定一个二叉树,找出其最小深度。
    最小深度是从根节点到最近叶子节点的最短路径上的节点数量。说明: 叶子节点是指没有子节点的节点。

本题最大的坑在于最小深度的定义上:定义为到叶子节点的距离,因此需要考虑当仅有一个叶子的时候不需要再去比较另一个分支

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int minDepth(TreeNode* root) {
        if (root == NULL)
            return 0;

        if (root->left == NULL)
            return 1 + minDepth(root->right);
        else if (root->right == NULL)
            return 1 + minDepth(root->left);
        else
            return 1 + min(minDepth(root->left), minDepth(root->right));
    }
};
  1. 路径总和
    给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。

遍历的过程中加上一个值的判断即可

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    bool hasPathSum(TreeNode* root, int sum) {
        if (root == NULL)
            return false;

        sum -= root->val;
        if (root->left == NULL && root->right == NULL)
        {
            if (sum == 0)
                return true;
            else return false;
        }

        return hasPathSum(root->left, sum) || hasPathSum(root->right, sum);
    }
};
发布了129 篇原创文章 · 获赞 15 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/u013354486/article/details/104876721
今日推荐