- Binary Tree Vertical Order Traversal
Given a binary tree, return the vertical order traversal of its nodes’ values. (ie, from top to bottom, column by column).
If two nodes are in the same row and column, the order should be from left to right.
Example
Example1
Inpurt: {3,9,20,#,#,15,7}
Output: [[9],[3,15],[20],[7]]
Explanation:
3
/
/
9 20
/
/
15 7
Example2
Input: {3,9,8,4,0,1,7}
Output: [[4],[9],[3,0,1],[8],[7]]
Explanation:
3
/
/
9 8
/\ /
/ /
4 01 7
解法1:按level遍历二叉树,遍历同时记录每个节点的从左往右的索引,左节点索引-1,右节点索引+1。
注意:
1)这题只能用按层次遍历,因为要保证同样索引的节点中,上面的节点排在前面。尝试了preOrder和InOrder遍历都不行。
2) 有可能右边某节点的左子节点的索引值反而排在左边某节点的右子节点的索引值前面(即相交了)。
代码如下:
这里的index就相当于解法2,3里面的pos。
/**
* Definition of TreeNode:
* class TreeNode {
* public:
* int val;
* TreeNode *left, *right;
* TreeNode(int val) {
* this->val = val;
* this->left = this->right = NULL;
* }
* }
*/
struct Node {
TreeNode * pTreeNode;
int index;
Node (TreeNode *pNode = NULL, int id = 0) : pTreeNode(pNode), index(id) {}
bool operator < (const Node & n) const {
return index < n.index;
}
};
class Solution {
public:
/**
* @param root: the root of tree
* @return: the vertical order traversal
*/
vector<vector<int>> verticalOrder(TreeNode * root) {
if (!root) return {};
vector<vector<int>> result;
inLevelOrderTraversal(root);
for (auto m : mp) {
result.push_back(m.second);
}
return result;
}
private:
map<int, vector<int>> mp; //index, values
void inLevelOrderTraversal(TreeNode * root) {
if (!root) return;
queue<Node> q;
q.push(Node(root, 0));
while(!q.empty()) {
Node node = q.front();
q.pop();
mp[node.index].push_back(node.pTreeNode->val);
if (node.pTreeNode->left) q.push(Node(node.pTreeNode->left, node.index - 1));
if (node.pTreeNode->right) q.push(Node(node.pTreeNode->right, node.index + 1));
}
}
};
下面的DFS解法不对:
如果输入是{3,9,8,4,0,1,7,#,#,#,2,5}
会输出[[4],[9,5],[3,0,1],[2,8],[7]]
而应该是
[[4],[9,5],[3,0,1],[8,2],[7]]
原因是该方法先处理左子树的节点,这样左子树的节点都在右子树的前面。而右子树的8是应该排在左子树的前面的。
要修改也可以,每个节点都必须再加一个depth,然后先比较pos,再比较depth。
class Solution {
public:
/**
* @param root: the root of tree
* @return: the vertical order traversal
*/
vector<vector<int>> verticalOrder(TreeNode *root) {
if (!root) return vector<vector<int>>();
map<int, vector<int>> sols;
helper(root, 0, sols);
vector<vector<int>> res;
for (auto sol : sols) {
res.push_back(sol.second);
}
return res;
}
private:
int minPos = INT_MAX, maxPos = 0;
void helper(TreeNode *root, int pos, map<int, vector<int>> &sols) {
if (root) {
sols[pos].push_back(root->val);
if (root->left) helper(root->left, pos - 1, sols);
if (root->right) helper(root->right, pos + 1, sols);
}
}
};
下面是修正的解法:
注意:我们不能只根据先pos后depth来排序,因为不能保证pos, depth相同的时候,左边的节点在前面!所以要根据处理时候的顺序index来。
试了前中后序遍历都可以。
/**
* Definition of TreeNode:
* class TreeNode {
* public:
* int val;
* TreeNode *left, *right;
* TreeNode(int val) {
* this->val = val;
* this->left = this->right = NULL;
* }
* }
*/
struct Node {
int val;
int depth;
int index;
Node(int v, int d, int i) : val(v), depth(d), index(i) {}
bool operator < (const Node &node) const {
if (depth == node.depth) return index < node.index;
return depth < node.depth;
}
};
class Solution {
public:
/**
* @param root: the root of tree
* @return: the vertical order traversal
*/
vector<vector<int>> verticalOrder(TreeNode *root) {
if (!root) return vector<vector<int>>();
map<int, set<Node>> sols;
helper(root, 0, 0, sols);
vector<vector<int>> res;
for (auto s : sols) {
vector<int> tmpVec;
for (auto node : s.second) {
tmpVec.push_back(node.val);
}
res.push_back(tmpVec);
}
return res;
}
private:
int minPos = INT_MAX, maxPos = 0;
int index = 0;
void helper(TreeNode *root, int pos, int depth, map<int, set<Node>> &sols) {
if (root) {
sols[pos].insert(Node(root->val, depth, index++));
if (root->left) helper(root->left, pos - 1, depth + 1, sols);
// sols[pos].insert(Node(root->val, depth, index++)); 中序也可以
if (root->right) helper(root->right, pos + 1, depth + 1, sols);
// sols[pos].insert(Node(root->val, depth, index++)); 后序也可以
}
}
};
三刷:不用Node,直接硬处理。
map<int, set<pair<int, pair<int, int>>>> mp; //<pos, set<{depth, {index, val}>
/**
* Definition of TreeNode:
* class TreeNode {
* public:
* int val;
* TreeNode *left, *right;
* TreeNode(int val) {
* this->val = val;
* this->left = this->right = NULL;
* }
* }
*/
class Solution {
public:
/**
* @param root: the root of tree
* @return: the vertical order traversal
*/
vector<vector<int>> verticalOrder(TreeNode *root) {
// write your code here
int depth = 0, index = 0;
helper(root, depth, index);
vector<vector<int>> res;
for (auto m : mp) {
res.push_back(vector<int>());
for (auto n : m.second) {
res.back().push_back(n.second.second);
}
}
return res;
}
private:
int index = 0;
map<int, set<pair<int, pair<int, int>>>> mp; //<pos, set<{depth, {index, val}>
void helper(TreeNode *root, int depth, int pos) {
if (!root) return;
mp[pos].insert({depth, {index++, root->val}});
helper(root->left, depth + 1, pos - 1);
helper(root->right, depth + 1, pos + 1);
}
};
本文探讨了二叉树的垂直遍历算法,通过不同遍历方式实现节点按列顺序输出,包括层级遍历和深度优先搜索的改进版本,确保同一列节点按从上到下、从左到右的正确顺序排列。
921





