The Wayback Machine - https://web.archive.org/web/20210125132134/https://github.com/grandyang/leetcode/issues/987
Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[LeetCode] 987. Vertical Order Traversal of a Binary Tree #987

Open
grandyang opened this issue May 30, 2019 · 0 comments
Open

[LeetCode] 987. Vertical Order Traversal of a Binary Tree #987

grandyang opened this issue May 30, 2019 · 0 comments

Comments

@grandyang
Copy link
Owner

@grandyang grandyang commented May 30, 2019

Given a binary tree, return the  vertical order  traversal of its nodes values.

For each node at position (X, Y), its left and right children respectively will be at positions (X-1, Y-1) and (X+1, Y-1).

Running a vertical line from X = -infinity to X = +infinity, whenever the vertical line touches some nodes, we report the values of the nodes in order from top to bottom (decreasing Y coordinates).

If two nodes have the same position, then the value of the node that is reported first is the value that is smaller.

Return an list of non-empty reports in order of X coordinate.  Every report will have a list of values of nodes.

Example 1:

Input: [3,9,20,null,null,15,7]
Output: [[9],[3,15],[20],[7]]
Explanation:
Without loss of generality, we can assume the root node is at position (0, 0):
Then, the node with value 9 occurs at position (-1, -1);
The nodes with values 3 and 15 occur at positions (0, 0) and (0, -2);
The node with value 20 occurs at position (1, -1);
The node with value 7 occurs at position (2, -2).

Example 2:

Input: [1,2,3,4,5,6,7]
Output: [[4],[2],[1,5,6],[3],[7]]
Explanation:
The node with value 5 and the node with value 6 have the same position according to the given scheme.
However, in the report "[1,5,6]", the node value of 5 comes first since 5 is smaller than 6.

Note:

  1. The tree will have between 1 and 1000 nodes.
  2. Each node's value will be between 0 and 1000.

这道题是让给二叉树进行竖直遍历,怎么隐约感觉以前做过这道题,结果去查了一下,果然有 Binary Tree Vertical Order Traversal。怎么把标题顺序调换一下就是一道新题,Excuse me???结果仔细研究一下,两道题还真有些不同,不同点就是在于这道题对于同一列中的结点值的顺序还有要求,此处应有尼克杨问号脸??就是说默认是按y值从大到小排列的,但如果y值相同,则按结点值从小到大排,我也是给跪了。好吧,你赢了,将就着做吧。这道题之所以比之前的那道类似的题目难,原因是把y值也扯进来了,那么数据结构中也要给y值留个位置,大体思路其实还是一样的。这里要用到比较复杂的数据结构,同时用到两个 TreeMap 嵌在一块。用 TreeMap 的好处就是可以自动排序了,外层的映射 key 是x值,这样保证了x值是从小到大的,符合题目中要求的顺序。内层的映射是y值和一个放结点值的 TreeSet,之所以使用 TreeSet 也是利用其可以自动排序的特点,因为当y值相同时,需要结点值从小到大排列。同理,在队列 queue 中也要把y值包含进去,这里可以用一个 pair 对儿,分别是结点和坐标值,初始时把根结点,还有其坐标放入队列开始遍历吧。遍历的过程其实并不难,就是取出队首结点,取出坐标,更新 TreeMap 中的映射,然后将存在的左右子结点加入队列中继续遍历。这里细心的读者会发现,为啥左右子结点的坐标的y值都是加1,而题目中明明写的减1啊?这是因为 TreeMap 是从小到大的默认顺序,而题目中要求的y值是从上到下递减,这样就是从大到小的顺序了,为了方便起见,改成加1,就可以得到题目中要求的顺序了,算是个小 trick 吧。当遍历结束后,所有的数据都存在了 TreeMap 中,只要遍历 TreeMap,并按顺序取出每列的结点值,组成数组放入结果 res 中即可,参见代码如下:

解法一:

class Solution {
public:
    vector<vector<int>> verticalTraversal(TreeNode* root) {
        vector<vector<int>> res;
        map<int, map<int, set<int>>> m;
        queue<pair<TreeNode*, vector<int>>> q;
        q.push({root, {0, 0}});
        while (!q.empty()) {
            auto t = q.front(); q.pop();
            TreeNode *node = t.first;
            int x = t.second[0], y = t.second[1];
            m[x][y].insert(node->val);
            if (node->left) q.push({node->left, {x - 1, y + 1}});
            if (node->right) q.push({node->right, {x + 1, y + 1}});
        }
        for (auto &a : m) {
            vector<int> col;
            for (auto &it : a.second) {
                col.insert(col.end(), it.second.begin(), it.second.end());
            }
            res.push_back(col);
        }
        return res;
    }
};

接下来是递归的写法,基本解题思路没有太大的区别,可以参见上面的讲解来理解,参见代码如下:

解法二:

class Solution {
public:
    vector<vector<int>> verticalTraversal(TreeNode* root) {
        vector<vector<int>> res;
        map<int, map<int, set<int>>> m;
        helper(root, 0, 0, m);
        for (auto &a : m) {
            vector<int> col;
            for (auto &it : a.second) {
                col.insert(col.end(), it.second.begin(), it.second.end());
            }
            res.push_back(col);
        }
        return res;
    }
    void helper(TreeNode* root, int x, int y, map<int, map<int, set<int>>>& m) {
        if (!root) return;
        m[x][y].insert(root->val);
        helper(root->left, x - 1, y + 1, m);
        helper(root->right, x + 1, y + 1, m);
    }
};

Github 同步地址:

#987

类似题目:

Binary Tree Vertical Order Traversal

参考资料:

https://leetcode.com/problems/vertical-order-traversal-of-a-binary-tree/

https://leetcode.com/problems/vertical-order-traversal-of-a-binary-tree/discuss/260502/C%2B%2B-BFSDFS

https://leetcode.com/problems/vertical-order-traversal-of-a-binary-tree/discuss/231140/Add-clarification-for-the-output-order

https://leetcode.com/problems/vertical-order-traversal-of-a-binary-tree/discuss/231125/Java-HashMap-and-TreeMap-and-PriorityQueue-Solution

LeetCode All in One 题目讲解汇总(持续更新中...)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
1 participant