早上做题,终于靠自己实力做出了多年都没有搞定的题目:非递归中序遍历二叉树。以前碰到这个题想很久想不出来,然后就去网上找一下别人的思路和答案,理解之后记住,然而,过段时间又忘了,下次碰到又得重新来。

这次终于在不查任何资料的情况下做出来了,对刷题又有了信心。

题目

LeetCode题目的中文描述如下:

给定一个二叉树,返回它的中序遍历。

示例:

输入: [1,null,2,3]
  1
   \
    2
   /
  3

输出: [1,3,2]

进阶: 递归算法很简单,你可以通过迭代算法完成吗?

英文描述如下:

Given a binary tree, return the inorder traversal of its nodes’ values.

Example:

Input: [1,null,2,3]
  1
   \
    2
   /
  3

Output: [1,3,2]

Follow up: Recursive solution is trivial, could you do it iteratively?

思路

看到要求非递归遍历,直接就能想到不用递归就得用迭代或栈来代替,而这个地明显就只能用栈1,确定用栈,剩下就是考虑怎么入栈和出栈,避免重复访问、遗漏等问题了,所以我在栈之外设计两个list保存已访问的元素(判断当前元素是否可以被访问)和正在栈中的元素(避免重复入栈)。

具体代码如下:

/**
 * 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:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> r;
        stack<TreeNode *> s;
        TreeNode * p = root;
        set<TreeNode *> st1; // 已访问的
        set<TreeNode *> st2;  // 已在栈中的

        while (p != NULL) {
            if (st1.count(p->left) > 0) {
                r.push_back(p->val);
                st1.insert(p);
                
                if (!s.empty()) {
                    p = s.top();
                    s.pop();
                    st2.erase(p);
                } else {
                    p = NULL;
                }
                
                continue;
            }
            
            if (p->right != NULL) {
                if (st1.count(p->right) == 0
                   && st2.count(p->right) == 0) {
                    s.push(p->right);
                    st2.insert(p->right);
                }
            }

            if (p->left != NULL) {
                s.push(p);
                s.push(p->left);
            } else {
                r.push_back(p->val);
                st1.insert(p);
            }
            if (!s.empty()) {
                p = s.top();
                s.pop();
                st2.erase(p);
            } else {
                p = NULL;
            }
        }
        return r;
    }
};

结果

最后也是一次AC,自己的基本功还是可以。

中序遍历二叉树结果
中序遍历二叉树结果

总结

看来刷题确实有助于提升思维,这个可以继续坚持下去。

Footnotes

1 比如二分查找,如果不用递归,就需要用迭代来完成。