代码随想录算法训练营day19

题目:654.最大二叉树、617.合并二叉树、700.二叉搜索树中的搜索、98.验证二叉搜索树

参考链接:代码随想录

654.最大二叉树

思路:做过根据中序后序数组构建二叉树后,这题比较容易,只需要找到最大值分割,然后递归构造即可。时间复杂度O(n),即为数组长度。

class Solution {
public:
    int findMaxIndex(vector<int>& nums){//默认不为空
        int max=INT_MIN;
        int i,maxIndex;
        for(i=0;i<nums.size();i++){
            if(nums[i]>max){
                max=nums[i];
                maxIndex=i;
            }
        }
        return maxIndex;
    }
    TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
        if(nums.empty()){
            return nullptr;
        }
        int maxIndex=findMaxIndex(nums);//也是分割点
        TreeNode* root=new TreeNode(nums[maxIndex]);//建立根节点
        vector<int> leftNums(nums.begin(),nums.begin()+maxIndex);//左闭右开
        vector<int> rightNums(nums.begin()+maxIndex+1,nums.end());
        root->left=constructMaximumBinaryTree(leftNums);
        root->right=constructMaximumBinaryTree(rightNums);
        return root;
    }
};

不建立新vector的优化写法:

class Solution {
public:
    int findMaxIndex(vector<int>& nums,int begin,int end){//默认不为空
        int max=INT_MIN;
        int i,maxIndex;
        for(i=begin;i<end;i++){
            if(nums[i]>max){
                max=nums[i];
                maxIndex=i;
            }
        }
        return maxIndex;
    }
    TreeNode* traversal(vector<int>& nums,int begin,int end){//左闭右开
        if(begin>=end){//数组为空
            return nullptr;
        }
        int maxIndex=findMaxIndex(nums,begin,end);
        TreeNode* root=new TreeNode(nums[maxIndex]);
        int leftBegin=begin;
        int leftEnd=maxIndex;
        int rightBegin=maxIndex+1;
        int rightEnd=end;
        root->left=traversal(nums,leftBegin,leftEnd);
        root->right=traversal(nums,rightBegin,rightEnd);
        return root;
    }
    TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
        return traversal(nums,0,nums.size());
    }
};

617.合并二叉树

思路:本题首先想到是正常遍历,采用前序遍历,同时遍历两棵树。
一开始错误代码:

class Solution {
public:
    TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
        TreeNode* node;
        if(!root1&&!root2){//两个同时遍历
            return nullptr;
        }
        else if(root1&&root2){
            node=new TreeNode(root1->val+root2->val);
        }
        else if(root1){//只有左边
            node=new TreeNode(root1->val);
        }
        else{
            node=new TreeNode(root2->val);
        }
        node->left=mergeTrees(root1->left,root2->left);
        node->right=mergeTrees(root1->right,root2->right);
        return node;
    }
};

主要问题是访问了空节点的左右孩子,造成runtime error。应该在一开始就优先判断返回情况,即两边有空的情况。

class Solution {
public:
    TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
        if(!root1&&!root2){//两个同时遍历
            return nullptr;
        }
        if(root1&&!root2){
            return root1;
        }
        if(!root1&&root2){//只有左边
            return root2;
        }
        TreeNode* node=new TreeNode(root1->val+root2->val);
        node->left=mergeTrees(root1->left,root2->left);
        node->right=mergeTrees(root1->right,root2->right);
        return node;
    }
};

看解析发现不需要建立新节点,直接在T1上合并即可。
标答:

class Solution {
public:
    TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) {
        if (t1 == NULL) return t2; // 如果t1为空,合并之后就应该是t2
        if (t2 == NULL) return t1; // 如果t2为空,合并之后就应该是t1
        // 修改了t1的数值和结构
        t1->left = mergeTrees(t1->left, t2->left);      // 左
        t1->right = mergeTrees(t1->right, t2->right);   // 右
        t1->val += t2->val;                             // 中
        return t1;
    }
};

迭代法pass。

700.二叉搜索树中的搜索

思路:首先了解BST,即所有左子树节点小于根节点的值,所有右子树的节点大于根节点的值,且其所有子树都是二叉搜索树。采用递归法比较容易想到。

class Solution {
public:
    TreeNode* searchBST(TreeNode* root, int val) {
        if(!root){//一开始结束条件
            return nullptr;
        }
        if(val==root->val){
            return root;
        }
        else if(val<root->val){
            return searchBST(root->left,val);
        }
        else{
            return searchBST(root->right,val);
        }
    }
};

根为空和值找到了可以合并。
标答:

class Solution {
public:
    TreeNode* searchBST(TreeNode* root, int val) {
        if (root == NULL || root->val == val) return root;
        TreeNode* result = NULL;
        if (root->val > val) result = searchBST(root->left, val);
        if (root->val < val) result = searchBST(root->right, val);
        return result;
    }
};

迭代法:由于BST的搜索路径已经固定好,不需要再使用栈和队列。

class Solution {
public:
    TreeNode* searchBST(TreeNode* root, int val) {
        TreeNode* cur=root;
        while(cur&&cur->val!=val){
            if(val<cur->val){
                cur=cur->left;
            }
            else{
                cur=cur->right;
            }
        }
        return cur;
    }
};

98.验证二叉搜索树

思路:二叉搜索树进行中序遍历,得到的序列递增,这就是我们的判断方法。判断序列递增的时候从头开始遍历,如果有一个不递增则break。只有序列长度为0或1或i遍历到倒数第二个,才说明序列递增。

class Solution {
public:
    void traverse(TreeNode* root,vector<int> &inorder){
        if(!root){
            return;
        }
        traverse(root->left,inorder);
        inorder.push_back(root->val);
        traverse(root->right,inorder);
    }
    bool isValidBST(TreeNode* root) {
        vector<int> inorder;
        traverse(root,inorder);
        int i;
        for(i=0;i<inorder.size()-1;i++){
            if(inorder[i]>=inorder[i+1]){
                break;
            }
        }
        if(inorder.empty()||inorder.size()== 1||i==inorder.size()-1){
            return true;
        }
        return false;
    }
};

标答简介一些:

class Solution {
private:
    vector<int> vec;
    void traversal(TreeNode* root) {
        if (root == NULL) return;
        traversal(root->left);
        vec.push_back(root->val); // 将二叉搜索树转换为有序数组
        traversal(root->right);
    }
public:
    bool isValidBST(TreeNode* root) {
        vec.clear(); // 不加这句在leetcode上也可以过,但最好加上
        traversal(root);
        for (int i = 1; i < vec.size(); i++) {
            // 注意要小于等于,搜索树里不能有相同元素
            if (vec[i] <= vec[i - 1]) return false;
        }
        return true;
    }
};

看标答发现可以在递归中直接比较,不用生成序列。
标答:

class Solution {
public:
    TreeNode* pre = NULL; // 用来记录前一个节点
    bool isValidBST(TreeNode* root) {
        if (root == NULL) return true;
        bool left = isValidBST(root->left);

        if (pre != NULL && pre->val >= root->val) return false;
        pre = root; // 记录前一个节点

        bool right = isValidBST(root->right);
        return left && right;
    }
};

迭代法pass

你可能感兴趣的:(算法)