LeetCode简易题解--098、099

来源:互联网 发布:软件的可维护性 编辑:程序博客网 时间:2024/05/16 09:55

98. Validate Binary Search Tree

题意简述:判断一颗二叉树是否是二叉搜索树(BST)。

Binary tree [2,1,3], return true.
Binary tree [1,2,3], return false.

中序遍历二叉树,判断得到的数组是否是升序的即可。用递归的方法也很简单,这里就不多说了。这里介绍的是非递归的方法。
非递归算法需要用到一个栈来做辅助。分为几个步骤:

  1. 首先从根节点开始,一直往左节点前进,将每一个节点都压入栈。这个过程做完之后,二叉树的最左边的节点都压入了栈。
  2. 将栈顶节点取出,此节点就是目前所遍历到的节点中最左边的节点。这个节点就是中序遍历最先访问的节点。
  3. 访问该节点(进行目标操作)。
  4. 令当前访问了的节点的右子节点为新的根节点,该子树成为新的二叉树以继续以上操作。

说明:第4个步骤其实就是递归地进行以上操作,只不过会以循环的形式进行。在向左子树一直前进的过程中,遇到的节点都被压入了栈,根据栈FIFO的性质,能够保证中序遍历的正确性。以上操作结束的边界是当前的根节点为NULL或者栈为空。
代码如下:

stack<TreeNode*> s;while (root != NULL || s.size() != 0) { // 步骤4的一部分以及操作结束的边界    while (root != NULL) { // 步骤1        s.push(root);        root = root->left;    }    root = s.top();    s.pop();    // 步骤3,目标操作    root = root->right; // 步骤4}

因此对这道题来说,在步骤3中将目前节点的值储存起来,得到的就是中序遍历的数组。判断数组是否是升序排序的即可。
最终提交的代码为:

class Solution {public:    bool isValidBST(TreeNode* root) {        if (root == NULL) return true;        stack<TreeNode*> s;        stack<int> vals;        while (root != NULL || s.size() != 0) {            while (root != NULL) {                s.push(root);                root = root->left;            }            root = s.top();            s.pop();            vals.push(root->val);            root = root->right;        }        int t1 = vals.top();        vals.pop();        while (vals.size() > 0) {            int t2 = vals.top();            vals.pop();            if (t1 <= t2) return false;            t1 = t2;        }        return true;    }};

99. Recover Binary Search Tree

题意简述:二叉搜索树中的两个节点被交换了,找出这两个节点并交换回来,恢复BST的正确性。
核心代码与上一题是一样的,不同的地方在于处理节点的方式。

执行过程中始终记录当前的节点root和这个节点的上一个节点pre。用big记录错误的较大的那个节点,small记录作物的较小的那个节点。由于BST中序遍历得到的数组是升序的,因此被交换的两个节点中,前面那个值肯定比后面那个的值大。此处的问题在于如何判断节点是否是错误节点。方法是:
在执行过程中,若是当前节点的值小于上一个节点的值,那么错误的节点就在这两个节点中;并且,第一次遇到时,pre是错误节点(较大的节点),第二次遇到时,root是错误节点(较小的节点)。
例如,对中序数组[1, 4, 3, 2, 5]root指向3时,错误节点为pre(4)root指向2时,错误节点为root(2)
以上我们假设会两次遇到错误节点,但是,如果错误节点相邻,那么只会遇到一次错误节点(此时前后两个节点都是错误节点)。因此,第一次遇到错误节点时,我们默认认为前后两个都是错误节点,用bigsmall记录下来。如果第二次遇到节点,说明上一次只有一个错误节点,并且此错误节点肯定是bigsmall的值是错误的,所以将small改为此时的root即可。完成以上操作,还需要一个标志位flag
找到这两个节点之后,将值交换即可。
最终代码如下:

class Solution {public:    void recoverTree(TreeNode* root) {        if (root == NULL) return;        TreeNode* ori_root = root;        stack<TreeNode*> s;        TreeNode* pre = NULL;        TreeNode* big = NULL;        TreeNode* small = NULL;        bool flag = true;        while (root != NULL || s.size() != 0) {            while (root != NULL) {                s.push(root);                root = root->left;            }            root = s.top();            s.pop();            if (pre != NULL && pre->val > root->val) {                if (flag) {                    big = pre;                    small = root;                    flag = false;                } else {                    small = root;                }            }            pre = root;            root = root->right;        }        int t = big->val;        big->val = small->val;        small->val = t;    }};
原创粉丝点击