Given the root
of a binary tree, calculate the vertical order traversal of the binary tree.
For each node at position (row, col)
, its left and right children will be at positions (row + 1, col - 1)
and (row + 1, col + 1)
respectively. The root of the tree is at (0, 0)
.
The vertical order traversal of a binary tree is a list of top-to-bottom orderings for each column index starting from the leftmost column and ending on the rightmost column. There may be multiple nodes in the same row and same column. In such a case, sort these nodes by their values.
Return the vertical order traversal of the binary tree.
Example 1:
Input: root = [3,9,20,null,null,15,7]
Output: [[9],[3,15],[20],[7]]
Explanation:
Column -1: Only node 9 is in this column.
Column 0: Nodes 3 and 15 are in this column in that order from top to bottom.
Column 1: Only node 20 is in this column.
Column 2: Only node 7 is in this column.
Example 2:
Input: root = [1,2,3,4,5,6,7]
Output: [[4],[2],[1,5,6],[3],[7]]
Explanation:
Column -2: Only node 4 is in this column.
Column -1: Only node 2 is in this column.
Column 0: Nodes 1, 5, and 6 are in this column.
1 is at the top, so it comes first.
5 and 6 are at the same position (2, 0), so we order them by their value, 5 before 6.
Column 1: Only node 3 is in this column.
Column 2: Only node 7 is in this column.
Example 3:
Input: root = [1,2,3,4,6,5,7]
Output: [[4],[2],[1,5,6],[3],[7]]
Explanation:
This case is the exact same as example 2, but with nodes 5 and 6 swapped.
Note that the solution remains the same since 5 and 6 are in the same location and should be ordered by their values.
Constraints:
- The number of nodes in the tree is in the range
[1, 1000]
. 0 <= Node.val <= 1000
這道題是讓給二叉樹進行豎直遍歷,怎么隱約感覺以前做過這道題,結果去查了一下,果然有 Binary Tree Vertical Order Traversal。怎么把標題順序調換一下就是一道新題,Excuse me???結果仔細研究一下,兩道題還真有些不同,不同點就是在於這道題對於同一列中的結點值的順序還有要求,此處應有尼克楊問號臉??就是說默認是按y值從大到小排列的,但如果y值相同,則按結點值從小到大排,我也是給跪了。好吧,你贏了,將就着做吧。這道題之所以比之前的那道類似的題目難,原因是把y值也扯進來了,那么數據結構中也要給y值留個位置,大體思路其實還是一樣的。這里要用到比較復雜的數據結構,同時用到兩個 TreeMap 嵌在一塊。用 TreeMap 的好處就是可以自動排序了,外層的映射 key 是x值,這樣保證了x值是從小到大的,符合題目中要求的順序。內層的映射是y值和一個放結點值的 TreeSet,之所以使用 TreeSet 也是利用其可以自動排序的特點,因為當y值相同時,需要結點值從小到大排列(但是后來 LeetCode 加了新的 test case [3,1,4,0,2,2],使得同一個y值時可能有相同的結點值,這樣就不能用 TreeSet 了,因為其會自動去重復,這里還是用 vector)。同理,在隊列 queue 中也要把y值包含進去,這里可以用一個 pair 對兒,分別是結點和坐標值,初始時把根結點,還有其坐標放入隊列開始遍歷吧。遍歷的過程其實並不難,就是取出隊首結點,取出坐標,更新 TreeMap 中的映射,然后將存在的左右子結點加入隊列中繼續遍歷。這里細心的讀者會發現,為啥左右子結點的坐標的y值都是加1,而題目中明明寫的減1啊?這是因為 TreeMap 是從小到大的默認順序,而題目中要求的y值是從上到下遞減,這樣就是從大到小的順序了,為了方便起見,改成加1,就可以得到題目中要求的順序了,算是個小 trick 吧。當遍歷結束后,所有的數據都存在了 TreeMap 中,只要遍歷 TreeMap,並按順序取出每列的結點值(這里由於之前改為了 vector,所以需要再排個序),組成數組放入結果 res 中即可,參見代碼如下:
解法一:
class Solution {
public:
vector<vector<int>> verticalTraversal(TreeNode* root) {
vector<vector<int>> res;
map<int, map<int, vector<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].push_back(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) {
sort(it.second.begin(), it.second.end());
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, vector<int>>> m;
helper(root, 0, 0, m);
for (auto &a : m) {
vector<int> col;
for (auto &it : a.second) {
sort(it.second.begin(), it.second.end());
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, vector<int>>>& m) {
if (!root) return;
m[x][y].push_back(root->val);
helper(root->left, x - 1, y + 1, m);
helper(root->right, x + 1, y + 1, m);
}
};
Github 同步地址:
https://github.com/grandyang/leetcode/issues/987
類似題目:
Binary Tree Vertical Order Traversal
參考資料:
https://leetcode.com/problems/vertical-order-traversal-of-a-binary-tree/