leetcode之二叉树类之二叉树中序遍历运用-----OJ173/230/98/99/285 二叉树迭代器/BST第K小元素/判断BST是否合法/恢复BST/二叉树下个节点

本文是关于二叉树中序遍历的运用的相关的一些题


1、OJ173二叉树迭代器

核心是实现next、hasnext两个方法,其实相当于中序遍历,但要求以一种类方法形式出现

因为需要实现hasnext,如果每次都做判断非常麻烦,所以比较好的方法就是:

1、初始时,像非递归中序遍历那样,左子树不停压栈,直到遇到空不能压入为止

此后:

2、hasnext就判断stk是否为空即可

3、next,就从pop弹出一个即可,每次弹出后,如果弹出的节点存在右子树,那么进行1,也就是把右子树不停入栈左子节点直到不能压入为止

这是最为方便合理的方式,不要每次弹出一个并判断,那样很麻烦且容易出错

OJ173代码:

class BSTIterator {
public:
    stack<TreeNode *> stk;
    
    BSTIterator(TreeNode *root) {
        while (root) {
            stk.push(root);
            root = root->left;
        }
    }

    /** @return whether we have a next smallest number */
    bool hasNext() {
        return !stk.empty();
    }

    /** @return the next smallest number */
    int next() {
        int v;
        if (!stk.empty()) {
            TreeNode *cur = stk.top();
            stk.pop();
            v = cur->val;
            if (cur->right) {
                cur = cur->right;
                while (cur) {
                    stk.push(cur);
                    cur = cur->left;
                }
            }
            return v;
        }
    }
};

2、OJ230求搜索二叉树的第K小的元素value

根据中序遍历的有序性,本题是典型的中序遍历

OJ230代码:

class Solution {
public:
    void helper (TreeNode *cur, int &k, int &res) {
        if (cur) {
            helper(cur->left, k, res);
            if (k == 1) {
                res = cur->val;
            }
            --k;
            helper(cur->right, k, res);
        }
    }
    
    int kthSmallest(TreeNode* root, int k) {
        int res;
        helper(root, k, res);
        return res;
    }
};

3、OJ99恢复搜索二叉树

搜索二叉树的两个节点被互换value,核心思路是利用中序遍历的有序性,通过查看中序遍历哪些部分乱序了,判断是哪2个节点被互换;

具体要思考理解到如下:

1、被互换的两个节点,可能是相邻的也可能不相邻,但不论是否相邻,当中序遍历发现当前节点value >= 上一个节点value时,说明上一个节点肯定有问题,当前节点可能也有问题,这时记录这两个问题节点;切记一定要同时记录两个问题节点,因为相邻节点被互换时,就是相邻两个节点;不相邻节点被互换时,则和当前节点无关;

2、然后继续中序遍历,当再发现当前节点value >= 上一个节点value时,也就找到了被互换的两个节点;如果再未找到问题节点,那么出问题的就是最初记录的两个问题节点,也就是说被互换的是两个相邻的节点;

所以程序在中序遍历时,要能够取得上一个节点,需要传一个引用;并且中序递归函数要传入两个问题节点的引用,中序遍历结束后互换这两个节点value即可;

OJ99代码:


class Solution {
public:
    void helper (TreeNode *cur, TreeNode *&pre, TreeNode *&wrong1, TreeNode *&wrong2) {
        if (cur) {
            helper(cur->left, pre, wrong1, wrong2);
            if (pre) {
                if (cur->val <= pre->val) {
                    if (!wrong1) {
                        wrong1 = pre;
                        wrong2 = cur;
                    } else {
                        wrong2 = cur;
                    }
                }
            }
            pre = cur;
            helper(cur->right, pre, wrong1, wrong2);
        }
    }
    
    void recoverTree(TreeNode* root) {
        if (!root) {
            return;
        }
        
        TreeNode *pre = nullptr, *wrong1 = nullptr, *wrong2 = nullptr;
        helper(root, pre, wrong1, wrong2);
        if (wrong1 && wrong2) {
            int v = wrong1->val;
            wrong1->val = wrong2->val;
            wrong2->val = v;
        }
    }
};

4、OJ285中序遍历下个节点

同OJ173方式


5、OJ98 validate binary search tree

判断一个二叉树是否为合法的搜索二叉树,注意,此题如果简单的先序遍历判断当前节点和其左右子节点的大小关系是不行的,因为子树下非直系更新的节点不符合大小关系的情况存在,如根节点为10,右子节点为15,右子节点的左子节点为6;

这时中序遍历派上用场了,即判断中序遍历序列,是否出现后边数比前边数小于等于的情况

OJ98代码:

class Solution {
public:
    void helper (TreeNode *cur, TreeNode *&prev, bool &res) {
        if (cur) {
            helper(cur->left, prev, res);
            if (prev) {
                if (prev->val >= cur->val) {
                    res = false;
                }
            }
            prev = cur;
            helper(cur->right, prev, res);
        }
    }
    
    bool isValidBST(TreeNode* root) {
        bool res = true;
        if (!root) {
            return res;
        }
        
        TreeNode *prev = nullptr;
        helper(root, prev, res);
        return res;
    }
};


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值