Open azl397985856 opened 3 years ago
DFS, update x and y when visit a node. Need to sort each group first by the y location, then by the value. Time. O(nlgn) Space. O(n)
class Solution:
def verticalTraversal(self, root: TreeNode) -> List[List[int]]:
by_x = defaultdict(list)
def dfs(node, x, y):
by_x[x].append((y, node.val))
if node.left:
dfs(node.left, x-1, y+1)
if node.right:
dfs(node.right, x+1, y+1)
dfs(root, 0, 0)
ret = []
for k in sorted(by_x.keys()):
ret.append([x[1] for x in sorted(by_x[k], key = lambda x: (x[0], x[1]))])
return ret
基于前序遍历来做, 使用一个哈希表, 记录每个node的 横坐标, 纵坐标和结点的value值,我用的哈希映射是 x -> (y, val)。
步骤:
1.计算坐标 直接使用数学上的标准的直角坐标系, 除了root的y=0, 其他node的y值均 < 0。
2.排序
排序规则:
class Solution {
unordered_map<int, vector<pair<int, int>>> dict; /* x -> array of (y, val), dict size: 不同x值的个数 */
int minX = 1000; /* 记录最左边结点的横坐标x, 为了方便后面从哈希表中找到同一条竖直扫描线上的点 */
public:
vector<vector<int>> verticalTraversal(TreeNode* root)
{
vector<vector<int>> res;
dfs(root, 0, 0);
int maxX = minX + dict.size() - 1;
for (int i = minX; i <= maxX; i++)
{
auto cmp = [](pair<int, int>& p1, pair<int, int>& p2)
{
if (p1.first != p2.first)
return (p1.first > p2.first);
return p1.second < p2.second;
};
auto arr = dict[i]; // array of (y, val) for given x
sort(arr.begin(), arr.end(), cmp);
vector<int> vLine;
for (int j = 0; j < arr.size(); j++)
vLine.push_back(arr[j].second);
res.push_back(vLine);
}
return res;
}
void dfs(TreeNode* root, int x, int y)
{
if (!root) return;
dict[x].push_back({y, root->val});
minX = min(minX, x);
dfs(root->left, x - 1, y - 1);
dfs(root->right, x + 1, y - 1);
}
};
哈希表+dfs遍历数组。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def verticalTraversal(self, root: TreeNode) -> List[List[int]]:
if root==None:
return []
from collections import defaultdict
d=defaultdict(list)
stk=[(root,0,0)]
d[0].append((root.val,0))
while len(stk)>0:
p,c,r=stk.pop()
if p.left!=None:
stk.append((p.left,c-1,r+1))
d[c-1].append((p.left.val,r+1))
if p.right!=None:
stk.append((p.right,c+1,r+1))
d[c+1].append((p.right.val,r+1))
m=list(d.keys())
m.sort()
res=[]
for i in m:
d[i].sort(key=lambda x:(x[1],x[0]))
temp=[t[0] for t in d[i]]
res.append(temp)
return res
时间复杂度:O(nlogn) ,对哈希表及哈希表内部元素进行了排序
空间复杂度:O(n) ,用哈希表存储每个节点
class Solution(object):
def verticalTraversal(self, root):
if not root:
return [[]]
def update(tree, row, column):
if not tree:
return
else:
column_dic[column].append([row, tree.val])
update(tree.left, row+1, column-1)
update(tree.right, row+1, column+1)
if root:
column_dic = defaultdict(list)
column_dic[0].append([0, root.val])
update(root.left, 1,-1)
update(root.right, 1, 1)
keys = column_dic.keys()
keys.sort()
result = []
for key in keys:
values = column_dic[key]
values.sort()
result.append([])
for [row, value] in values:
result[-1].append(value)
return result
class Solution {
Map<TreeNode, Integer> node2col = new HashMap<>(), node2row = new HashMap<>();
Map<Integer, Map<Integer, List<Integer>>> col2row2nodes = new HashMap<>();
public List<List<Integer>> verticalTraversal(TreeNode root) {
List<List<Integer>> ans = new ArrayList<>();
node2col.put(root, 0);
node2row.put(root, 0);
dfs1(root);
dfs2(root);
List<Integer> cols = new ArrayList<>(col2row2nodes.keySet());
Collections.sort(cols);
for (int col : cols) {
Map<Integer, List<Integer>> row2nodes = col2row2nodes.get(col);
List<Integer> rows = new ArrayList<>(row2nodes.keySet());
Collections.sort(rows);
List<Integer> cur = new ArrayList<>();
for (int row : rows) {
List<Integer> nodes = row2nodes.get(row);
Collections.sort(nodes);
cur.addAll(nodes);
}
ans.add(cur);
}
return ans;
}
void dfs2(TreeNode root) {
if (root == null) return ;
int col = node2col.get(root), row = node2row.get(root);
Map<Integer, List<Integer>> row2nodes = col2row2nodes.getOrDefault(col, new HashMap<>());
List<Integer> nodes = row2nodes.getOrDefault(row, new ArrayList<>());
nodes.add(root.val);
row2nodes.put(row, nodes);
col2row2nodes.put(col, row2nodes);
dfs2(root.left);
dfs2(root.right);
}
void dfs1(TreeNode root) {
if (root == null) return ;
if (root.left != null) {
int col = node2col.get(root);
node2col.put(root.left, col - 1);
int row = node2row.get(root);
node2row.put(root.left, row + 1);
dfs1(root.left);
}
if (root.right != null) {
int col = node2col.get(root);
node2col.put(root.right, col + 1);
int row = node2row.get(root);
node2row.put(root.right, row + 1);
dfs1(root.right);
}
}
}
复杂度分析
令 n 为数组长度。
https://leetcode-cn.com/problems/vertical-order-traversal-of-a-binary-tree/
牵涉到排序,使用TreeMap来存row的值作为key,value为一个TreeMap,key为col的值,value为PQ来存当前col的所有value,并进行dfs。
class Solution {
public List<List<Integer>> verticalTraversal(TreeNode root) {
TreeMap<Integer, TreeMap<Integer, PriorityQueue<Integer>>> map = new TreeMap<>();
List<List<Integer>> res = new ArrayList<>();
helper(root, 0, 0, map);
for(TreeMap<Integer, PriorityQueue<Integer>> col : map.values()) {
res.add(new ArrayList<>());
for(PriorityQueue<Integer> nodes : col.values()) {
while(!nodes.isEmpty()) {
res.get(res.size() - 1).add(nodes.poll());
}
}
}
return res;
}
private void helper(TreeNode root, int row, int col, TreeMap<Integer, TreeMap<Integer, PriorityQueue<Integer>>> map) {
if(root == null) return;
if(!map.containsKey(row)) {
map.put(row, new TreeMap<>());
}
if(!map.get(row).containsKey(col)) {
map.get(row).put(col, new PriorityQueue<>());
}
map.get(row).get(col).offer(root.val);
helper(root.left, row - 1, col + 1, map);
helper(root.right, row + 1, col + 1, map);
}
}
O(nlogn)
O(n)
class Solution {
public List<List<Integer>> verticalTraversal(TreeNode root) {
List<List<Integer>> res = new ArrayList<>();
int[] boundary = new int[2];
Map<Integer, TreeMap<Integer, PriorityQueue<Integer>>> map = new HashMap<>();
generateMap(map, root, 0, 0, boundary);
for (int i = boundary[0]; i <= boundary[1]; i++) {
List<Integer> cur = new ArrayList<>();
for (Map.Entry<Integer, PriorityQueue<Integer>> entry : map.get(i).entrySet()) {
while (!entry.getValue().isEmpty()) cur.add(entry.getValue().poll());
}
res.add(cur);
}
return res;
}
private void generateMap(Map<Integer, TreeMap<Integer, PriorityQueue<Integer>>> map, TreeNode root, int x, int y, int[] boundary) {
if (root == null) return;
boundary[0] = Math.min(x, boundary[0]);
boundary[1] = Math.max(x, boundary[1]);
map.putIfAbsent(x, new TreeMap<>());
map.get(x).putIfAbsent(y, new PriorityQueue<>());
map.get(x).get(y).add(root.val);
generateMap(map, root.left, x - 1, y + 1, boundary);
generateMap(map, root.right, x + 1, y + 1, boundary);
}
}
Hashmap + BFS
class Solution(object):
def verticalTraversal(self, root):
"""
:type root: TreeNode
:rtype: List[List[int]]
"""
# bfs
if not root:
return None
hmap=collections.defaultdict(list)
stack=[(root,0,0)]
hmap[0].append((0,root.val))
while stack:
temp = []
for node,x,y in stack:
if node.left:
temp.append((node.left,x+1,y-1))
hmap[y-1].append((x+1,node.left.val))
if node.right:
temp.append((node.right,x+1,y+1))
hmap[y+1].append((x+1,node.right.val))
stack=temp
res=[]
for k in sorted(hmap.keys()):
res.append([node for y, node in sorted(hmap[k], key=lambda x:(x[0],x[1]))])
return res
时间复杂度: O(NLogN) 空间复杂度: O(N)
In order traversal, 对当前node的row和col进行储存。使用TreeMap进行储存,从而保证取出keySet的时候key都是排序过的。 同时也使用priority queue来满足当多个node同时出现在一个位置时候,照他们的值进行排序。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<List<Integer>> verticalTraversal(TreeNode root) {
Map<Integer, TreeMap<Integer, PriorityQueue<Integer>>> map = new TreeMap<>();
if (root == null) {
return new ArrayList<>();
}
List<List<Integer>> result = new ArrayList<>();
dfs(root, map, 0, 0);
for (int k : map.keySet()) {
List<Integer> curr = new ArrayList<>();
TreeMap<Integer, PriorityQueue<Integer>> m = map.get(k);
for (int c : m.keySet()) {
PriorityQueue<Integer> pq = m.get(c);
while (!pq.isEmpty()) {
curr.add(pq.poll());
}
}
result.add(curr);
}
return result;
}
private void dfs(TreeNode node, Map<Integer, TreeMap<Integer, PriorityQueue<Integer>>> map, int col, int row) {
if (node == null) return;
map.putIfAbsent(col, new TreeMap<>());
map.get(col).putIfAbsent(row, new PriorityQueue<>());
map.get(col).get(row).add(node.val);
dfs(node.left, map, col - 1, row + 1);
dfs(node.right, map, col + 1, row + 1);
}
}
时间复杂度: O(nlogn), 因为对TreeMap和PriorityQueue都有O(n)次插入和取出 空间复杂度: O(n)
BFS
fun verticalTraversal(root: TreeNode?): List<List<Int>> {
root ?: return emptyList()
val map = mutableMapOf<Int, MutableList<Int>>()
val queue = mutableListOf<Pair<TreeNode, Int>>()
queue.add(root to 0)
map.getOrPut(0) { mutableListOf<Int>() }.add(root.value)
var min = 0
var max = 0
while (queue.isNotEmpty()) {
val size = queue.size
val inner = mutableMapOf<Int, MutableList<Int>>()
repeat(size) {
val (node, loc) = queue.removeFirst()
node.left?.apply {
inner.getOrPut(loc - 1) { mutableListOf<Int>() }.add(value)
queue.add(this to loc - 1)
}
node.right?.apply {
inner.getOrPut(loc + 1) { mutableListOf<Int>() }.add(value)
queue.add(this to loc + 1)
}
}
inner.forEach { (key, value) ->
min = minOf(min, key)
max = maxOf(max, key)
value.sort()
map.getOrPut(key) { mutableListOf<Int>() }.addAll(value)
}
}
val res = mutableListOf<List<Int>>()
(min..max).forEach { loc ->
map[loc]?.let {
res.add(it)
}
}
return res
}
O(n)
https://leetcode.com/problems/vertical-order-traversal-of-a-binary-tree/
const verticalTraversal = function (root) {
const nodeInfos = []; // holds the x, y, & val information of each node traversed
getNodeInfos(root, 0, 0);
// sort by the following order of importance:
// 1. x - coordinate
// 2. y - coordinate precedence given to higher value
// 3. node val in ascending order
nodeInfos.sort((a, b) => a[0] - b[0] || b[1] - a[1] || a[2] - b[2]);
const map = new Map();
for (const [x, y, val] of nodeInfos) {
if (!map.has(x)) map.set(x, []);
map.get(x).push(val);
}
return [...map.values()];
function getNodeInfos(node, x, y) {
if (node) {
getNodeInfos(node.left, x - 1, y - 1); // traverse left
nodeInfos.push([x, y, node.val]);
getNodeInfos(node.right, x + 1, y - 1); // traverse right
}
}
};
时间: O(nlogn) 空间: O(n)
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def verticalTraversal(self, root: TreeNode) -> List[List[int]]:
seen = defaultdict(lambda: defaultdict(list))
def dfs(x, y, root):
if not root:
return
seen[x][y].append(root.val)
dfs(x-1, y+1, root.left)
dfs(x+1, y+1, root.right)
dfs(0, 0, root)
res = []
for x in sorted(seen):
level = []
for y in sorted(seen[x]):
level += sorted(seen[x][y])
res.append(level)
return res
C++ Code:
class Solution {
public:
vector<vector<int>> verticalTraversal(TreeNode* root) {
vector<map<int, multiset<int>>> record;
int minCol = INT_MAX;
int maxCol = INT_MIN;
dfs(record, root, 0, 0, minCol, maxCol);
vector<vector<int>> ret(maxCol - minCol +1);
for(int i=0; i< record.size(); i++)
{
for(map<int, multiset<int>>::iterator it = record[i].begin(); it !=record[i].end(); it++)
{
for(multiset<int>::iterator it2 = (*it).second.begin(); it2!=(*it).second.end(); it2++)
ret[(*it).first- minCol].push_back((*it2));
}
record[i].clear();
}
return ret;
}
void dfs(vector<map<int, multiset<int>>>& record, TreeNode* root, int row, int col, int& minCol, int & maxCol)
{
if(root==NULL)
return ;
if(row+1>record.size())
record.resize(row+1);
record[row][col].insert(root->val);
minCol = min(col, minCol);
maxCol = max(col, maxCol);
dfs(record, root->left, row+1, col-1,minCol, maxCol);
dfs(record, root->right, row+1, col+1, minCol, maxCol);
}
};
class Solution {
public:
vector<vector<int>> verticalTraversal(TreeNode* root) {
vector<vector<int>> ret;
if(root==NULL)
return ret;
vector<map<int, multiset<int>>> record;
queue<pair<TreeNode*, int>> que;
que.push(make_pair(root,0));
int row =0;
int minCol = INT_MAX;
int maxCol = INT_MIN;
while(que.size())
{
int iSize = que.size();
record.resize(row+1);
for(int i=0; i< iSize; i++)
{
pair<TreeNode*, int> top = que.front();
int col = top.second;
que.pop();
record[row][col].insert(top.first->val);
minCol = min(col, minCol);
maxCol = max(col, maxCol);
if(top.first->left)
que.push(make_pair(top.first->left, col-1));
if(top.first->right)
que.push(make_pair(top.first->right, col+1));
}
row++;
}
ret.resize(maxCol - minCol+1);
for(int i=0; i< record.size(); i++)
{
for(map<int, multiset<int>>::iterator it = record[i].begin(); it !=record[i].end(); it++)
{
for(multiset<int>::iterator it2 = (*it).second.begin(); it2!=(*it).second.end(); it2++)
ret[(*it).first- minCol].push_back((*it2));
}
record[i].clear();
}
return ret;
}
};
class Solution:
def verticalTraversal(self, root: Optional[TreeNode]) -> List[List[int]]:
values = {}
def dfs(root, v, h):
nonlocal values
if not root:
return
if h in values:
values[h].append((v, root.val))
else:
values[h] = [(v, root.val)]
dfs(root.left, v + 1, h - 1)
dfs(root.right, v + 1, h + 1)
dfs(root, 0, 0)
res = []
for key in sorted(values):
column = [item[-1] for item in sorted(values[key])]
res.append(column)
print(res)
return res
时间复杂度 O(NlogN) 空间复杂度 O(N)
AC
AC
//heap
class Solution {
public List<List<Integer>> verticalTraversal(TreeNode root) {
PriorityQueue<Tuple> nodes = new PriorityQueue<>((t1, t2)->t1.col - t2.col);
preorder(root, nodes, 0, 0);
List<List<Integer>> result = new ArrayList<>();
List<Tuple> colNodes = new ArrayList<>();
int curCol = nodes.peek().col;
while(!nodes.isEmpty()){
if(nodes.peek().col != curCol){
Collections.sort(colNodes, Comparator.<Tuple>comparingInt(o->o.row).thenComparing(o->o.value));
List<Integer> r = new ArrayList<>();
for(Tuple t: colNodes){
r.add(t.value);
}
result.add(new ArrayList<>(r));
colNodes.clear();
curCol = nodes.peek().col;
} else {
Tuple cur = nodes.poll();
colNodes.add(cur);
}
}
Collections.sort(colNodes, Comparator.<Tuple>comparingInt(o->o.row).thenComparing(o->o.value));
List<Integer> r = new ArrayList<>();
for(Tuple t: colNodes){
r.add(t.value);
}
result.add(new ArrayList<>(r));
return result;
}
public PriorityQueue<Tuple> preorder(TreeNode root, PriorityQueue<Tuple> nodes, int row, int col){
if(root == null) {
return nodes;
}
Tuple rootT = new Tuple(row, col, root.val);
nodes.add(rootT);
preorder(root.left, nodes, row+1, col-1);
preorder(root.right, nodes, row+1, col+1);
return nodes;
}
private class Tuple{
int row;
int col;
int value;
public Tuple(int row, int col, int value){
this.row = row;
this.col = col;
this.value = value;
}
}
}
//TreeMap + heap
class Solution {
public List<List<Integer>> verticalTraversal(TreeNode root) {
TreeMap<Integer, TreeMap<Integer, PriorityQueue<Integer>>> map = new TreeMap<>();
preorder(root, map, 0, 0);
List<List<Integer>> result = new ArrayList<>();
for(int col: map.keySet()){
List<Integer> curCol = new ArrayList<>();
for(int row: map.get(col).keySet()){
PriorityQueue<Integer> pq = map.get(col).get(row);
while(!pq.isEmpty()){
curCol.add(pq.poll());
}
}
result.add(curCol);
}
return result;
}
public TreeMap<Integer, TreeMap<Integer, PriorityQueue<Integer>>> preorder(TreeNode root, TreeMap<Integer, TreeMap<Integer, PriorityQueue<Integer>>> map, int row, int col){
if(root == null) {
return map;
}
map.putIfAbsent(col, new TreeMap<>());
map.get(col).putIfAbsent(row, new PriorityQueue<>());
map.get(col).get(row).add(root.val);
preorder(root.left, map, row+1, col-1);
preorder(root.right, map, row+1, col+1);
return map;
}
}
time: preorder需要遍历每个node,O(N);外部循环需要在遍历每个node,每个O(logN),总共O(NlogN);因此综合来说O(NlogN) space: 需要额外的空间存储heap/map,O(N)
class Solution {
public List<List
private void generateMap(Map<Integer, TreeMap<Integer, PriorityQueue<Integer>>> map, TreeNode root, int x, int y, int[] boundary) {
if (root == null) return;
boundary[0] = Math.min(x, boundary[0]);
boundary[1] = Math.max(x, boundary[1]);
map.putIfAbsent(x, new TreeMap<>());
map.get(x).putIfAbsent(y, new PriorityQueue<>());
map.get(x).get(y).add(root.val);
generateMap(map, root.left, x - 1, y + 1, boundary);
generateMap(map, root.right, x + 1, y + 1, boundary);
}
}
class Solution {
public List<List<Integer>> verticalTraversal(TreeNode root) {
List<int[]> nodes = new ArrayList<>();
dfs(root, 0, 0, nodes);
Collections.sort(nodes, (a, b)->{
if (a[0] != b[0]) return a[0] - b[0];
if (a[1] != b[1]) return a[1] - b[1];
return a[2] - b[2];
});
List<List<Integer>> res = new ArrayList<>();
int size = 0, col_0 = Integer.MIN_VALUE;
for (int[] list : nodes) {
int col = list[0], row = list[1], val = list[2];
if (col_0 != col) {
col_0 = col;
res.add(new ArrayList<Integer>());
size ++;
}
res.get(size - 1).add(val);
}
return res;
}
public void dfs(TreeNode node, int col, int row, List<int[]> nodes) {
if (node == null) return;
nodes.add(new int[]{col, row, node.val});
dfs(node.left, col - 1, row + 1, nodes);
dfs(node.right, col + 1, row + 1, nodes);
}
}
class Solution {
TreeMap<Integer, List<Info>> map;
public List<List<Integer>> verticalTraversal(TreeNode root) {
map = new TreeMap<>();
dfs(root, 0, 0);
List<List<Integer>> result = new ArrayList();
for (int key : map.keySet()) {
List<Integer> list = new ArrayList();
List<Info> tempList = map.get(key);
Collections.sort(tempList, (a, b) -> a.level == b.level ? a.node.val - b.node.val : a.level - b.level);
for (Info info : map.get(key)) {
list.add(info.node.val);
}
result.add(list);
}
return result;
}
private void dfs(TreeNode root, int level, int pos) {
if (root == null) {
return;
}
if (map.get(pos) == null) {
map.put(pos, new ArrayList<Info>());
}
map.get(pos).add(new Info(root, level, pos));
dfs(root.left, level + 1, pos - 1);
dfs(root.right, level + 1, pos + 1);
}
private static class Info {
TreeNode node;
int level;
int pos;
public Info(TreeNode node, int level, int pos) {
this.node = node;
this.level = level;
this.pos = pos;
}
}
}
哈希表储存列及深度的坐标,再在最后计算时统一排序
JavaScript Code
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} root
* @return {number[][]}
*/
var verticalTraversal = function(root) {
const map = new Map();
function cal(node, depth, col) {
if (!map.get(col)) map.set(col, new Map());
if (!map.get(col).get(depth)) map.get(col).set(depth, []);
map.get(col).get(depth).push(node.val);
if (node.left) {
cal(node.left, depth + 1, col - 1);
}
if (node.right) {
cal(node.right, depth + 1, col + 1);
}
}
cal(root, 1, 0);
const res = [];
Array.from(map.keys()).sort((a, b) => a - b).forEach((col) => {
const colTemp = [];
Array.from(map.get(col).keys()).sort((a, b) => a - b).forEach(depth => {
colTemp.push(...map.get(col).get(depth).sort((a,b) => a-b));
});
res.push(colTemp);
})
return res;
};
空间复杂度:O(N)
时间复杂度:O(N ^ 2)
先用BFS得到每个node 的column level, row level 和 value的tuple 存到数组,然后再对数组进行排序,最后遍历数组按照column level从小到大 加到不同的result的sub array里面
from collections import deque
class Solution:
def verticalTraversal(self, root: Optional[TreeNode]) -> List[List[int]]:
level_result = []
queue = deque([(root, 0)])
level = -1
while queue:
level += 1
level_size = len(queue)
for _ in range(level_size):
node, v_level = queue.pop()
level_result.append((v_level, level, node.val))
if node.left:
queue.appendleft((node.left, v_level - 1))
if node.right:
queue.appendleft((node.right, v_level + 1))
level_result.sort()
previous_v_level = None
result = []
for v_level, _, val in level_result:
if v_level != previous_v_level:
result.append([])
previous_v_level = v_level
if v_level == previous_v_level:
result[-1].append(val)
return result
Time O(nlgn)
Space O(n)
先用dfs遍历,并记录下所有节点的位置。然后输出排序。
class Solution:
import collections
def verticalTraversal(self, root: Optional[TreeNode]) -> List[List[int]]:
self.dicts = collections.defaultdict(lambda: collections.defaultdict(list))
self.dfs(root, 0 ,0)
result = list()
for x in sorted(self.dicts):
level = list()
for y in sorted(self.dicts[x]):
level += sorted(self.dicts[x][y])
result.append(level)
return result
def dfs(self, node, row, col):
if not node:
return
self.dicts[row][col].append(node.val)
self.dfs(node.left, row - 1, col + 1)
self.dfs(node.right, row + 1, col + 1)
时间复杂度 :O(NlogN)
空间复杂度:O(N)
思路: 先建立一个hashmap,并且建立min_col, max_col 记录最大最小列数变量。 dfs时维护当前行数和列数,dfs遍历hashmap当前列数对应当前行数和节点数值,并且更新min_col和max_col。由于题目要求坐标一样的节点返回时需要排列节点数值,在dfs之后对hashmap里每列里的(行数,节点数值)进行字典序排序(即直接sort)。 Python 3 code:
class Solution:
def verticalTraversal(self, root: Optional[TreeNode]) -> List[List[int]]:
if not root: return root
min_col = max_col = 0
colhash = defaultdict(list)
def dfs(node, row, column):
nonlocal min_col, max_col, colhash
if node:
min_col = min(min_col, column)
max_col = max(max_col, column)
colhash[column].append((row, node.val))
dfs(node.left, row + 1, column - 1)
dfs(node.right, row + 1, column + 1)
dfs(root,0,0)
res = []
for col in range(min_col, max_col + 1):
colhash[col].sort() #automatic lexicographical sort
colvals = [val for row, val in colhash[col]]
res.append(colvals)
return res
Time Complexity: O(WHlog(H)) = O(Nlog(H)) W = 二叉树总列数(宽度),H = 二叉树高度 , N 二叉树节点总数 dfs需要O(N)时间因为遍历每个节点一次。然后我们对每列的节点数值进行排序,因为每列最多有H/2个节点, 最多需要HO(log(H))时间 因为一共有W列, 最终时间为O(WHlog(H))
Space Complexity: O(N) dfs需要的最多空间
class Solution {
Map<Integer, PriorityQueue<int[]>> map; // <col: int[]{row, val}>
int minCol = Integer.MAX_VALUE;
int maxCol = Integer.MIN_VALUE;
public List<List<Integer>> verticalTraversal(TreeNode root) {
this.map = new HashMap<>();
helper(root, 0, 0);
List<List<Integer>> list = new ArrayList<>();
for (int i = minCol; i <= maxCol; i++) {
if (map.get(i) == null) continue;
List<Integer> temp = new ArrayList<>();
while (!map.get(i).isEmpty()) {
temp.add(map.get(i).poll()[1]);
}
list.add(temp);
}
return list;
}
private void helper(TreeNode node, int row, int col) {
if (node == null) return;
minCol = Math.min(minCol, col);
maxCol = Math.max(maxCol, col);
map.putIfAbsent(col, new PriorityQueue<>((a, b) -> a[0] == b[0] ? a[1] - b[1] : a[0] - b[0]));
map.get(col).offer(new int[]{row, node.val});
helper(node.left, row+1, col-1);
helper(node.right, row+1, col+1);
}
}
Time: O(nlogn) Space: O(n)
思路:
复杂度分析:
代码(C++):
1.
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<vector<int>> verticalTraversal(TreeNode* root)
map<int, vector<pair<int, int>>> tree;
// traverse from root node to all nodes and store node info (x, pair<y, val> ) into hashmap
dfs(root, tree, 0, 0);
vector<vector<int>> res;
for (auto it : tree) {
vector<pair<int, int>> vert = it.second;
sort(vert.begin(), vert.end(),
[](const pair<int, int>& a, const pair<int, int>& b) {
return (a.first < b.first) || (a.first == b.first) && (a.second < b.second); // first compare row:y, if same row then compare value
});
vector<int> vals;
for (auto val : vert)
vals.push_back(val.second);
res.push_back(vals);
vals.clear();
vert.clear();
}
return res;
}
private:
void dfs(TreeNode* node, map<int, vector<pair<int,int>>>& tree, int x, int y) {
if (!node) return;
tree[x].push_back({y, node->val});
dfs(node->left, tree, x - 1, y + 1);
dfs(node->right, tree, x + 1, y + 1);
}
};
After traversal, sorted by col first, then row, finally value.
class Solution(object):
def verticalTraversal(self, root):
"""
:type root: TreeNode
:rtype: List[List[int]]
"""
def dfs(node, row = 0, col = 0):
if not node:
return
hashmap[col][row].append(node.val)
dfs(node.left, row + 1, col - 1)
dfs(node.right, row + 1, col + 1)
# hashmap = dict()
hashmap = collections.defaultdict(
lambda: collections.defaultdict(list))
dfs(root)
res = []
for col in sorted(hashmap):
level = []
for row in sorted(hashmap[col]):
level += sorted(val for val in hashmap[col][row])
res.append(level)
return res
T: O(nlogn), n is the number of nodes, sorting is nlogn S: O(n)
class Solution {
public:
struct cmp{
bool operator()(pair<int,int>&a, pair<int,int>&b) {
if(a.second == b.second) {
return a.first < b.first;
}
return a.second < b.second;
}
};
vector<vector<int>> verticalTraversal(TreeNode* root) {
map<int, vector<pair<int, int>>> m;
queue<pair<TreeNode*,int>> q;
queue<int> indxQ;
indxQ.push(0);
q.push({root,0});
while(!q.empty()) {
int tempIndx = indxQ.front();
auto tempNode = q.front();
indxQ.pop();
q.pop();
m[tempIndx].push_back({tempNode.first->val, tempNode.second});
if(tempNode.first->left) {
q.push({tempNode.first->left, tempNode.second + 1});
indxQ.push(tempIndx - 1);
}
if(tempNode.first->right) {
q.push({tempNode.first->right, tempNode.second + 1});
indxQ.push(tempIndx + 1);
}
}
vector<vector<int>> res;
for(auto pair:m) {
vector<int> levelRes = sortVal(pair.second);
res.push_back(levelRes);
}
return res;
}
vector<int> sortVal (vector<pair<int, int>> val) {
vector<int> res;
sort(val.begin(), val.end(), cmp());
for(auto v:val) {
res.push_back(v.first);
}
return res;
}
};
DFS
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def verticalTraversal(self, root: Optional[TreeNode]) -> List[List[int]]:
node_list = []
def DFS(node, row, column):
if node is not None:
node_list.append((column, row, node.val))
DFS(node.left, row + 1, column - 1)
DFS(node.right, row + 1, column + 1)
DFS(root, 0, 0)
node_list.sort()
ans = []
cur_column_index = node_list[0][0]
cur_column = []
for column, row, value in node_list:
if column == cur_column_index:
cur_column.append(value)
else:
ans.append(cur_column)
cur_column_index = column
cur_column = [value]
ans.append(cur_column)
return ans
T: O(NlogN) S: O(N)
class Solution:
def verticalTraversal(self, root: TreeNode) -> List[List[int]]:
node_list = []
def BFS(root):
queue = deque([(root, 0, 0)])
while queue:
node, row, column = queue.popleft()
if node is not None:
node_list.append((column, row, node.val))
queue.append((node.left, row + 1, column - 1))
queue.append((node.right, row + 1, column + 1))
# step 1). construct the global node list, with the coordinates
BFS(root)
# step 2). sort the global node list, according to the coordinates
node_list.sort()
# step 3). retrieve the sorted results partitioned by the column index
ret = OrderedDict()
for column, row, value in node_list:
if column in ret:
ret[column].append(value)
else:
ret[column] = [value]
return ret.values()
space: O(n)
time: nlogn
class Solution {
public List<List<Integer>> verticalTraversal(TreeNode root) {
//TreeMap<K(col), TreeMap<K(row), PQ(val)>>
TreeMap<Integer, TreeMap<Integer, PriorityQueue<Integer>>> mapping = new TreeMap<>();
if (root == null) {
return new ArrayList<>();
}
dfs (root, mapping, 0, 0);
List<List<Integer>> res = new ArrayList<>();
for (Integer col : mapping.keySet()) {
TreeMap<Integer, PriorityQueue<Integer>> rowMap = mapping.get(col);
List<Integer> tempRes = new ArrayList<>();
for (Integer row : rowMap.keySet()) {
PriorityQueue<Integer> curList = rowMap.get(row);
int size = curList.size();
for (int i = 0; i < size; i++) {
tempRes.add(curList.poll());
}
}
res.add(tempRes);
}
return res;
}
public void dfs(TreeNode root, TreeMap<Integer, TreeMap<Integer, PriorityQueue<Integer>>> mapping, int col, int row) {
if (root == null) {
return;
}
if (!mapping.containsKey(col)) {
mapping.put(col, new TreeMap<Integer, PriorityQueue<Integer>>());
}
if (!mapping.get(col).containsKey(row)) {
mapping.get(col).put(row, new PriorityQueue<Integer>());
}
mapping.get(col).get(row).add(root.val);
dfs(root.left, mapping, col - 1, row + 1);
dfs(root.right, mapping, col + 1, row + 1);
}
}
DFS+坐标排序
C++ Code:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
struct Node {
int x,y,val;
Node(){}
Node(int a, int b, int c):x(a), y(b), val(c){}
bool operator < (Node node) const{
if(y!=node.y) return y>node.y;
else if(x!=node.x) return x>node.x;
return val>node.val;
}
};
map<int, priority_queue<Node>> mm;
vector<vector<int>> ans;
void dfs(int x, int y, TreeNode *root){
if(root==nullptr) return ;
mm[y].push({x, y, root->val});
dfs(x+1,y-1,root->left);
dfs(x+1,y+1,root->right);
return ;
}
vector<vector<int>> verticalTraversal(TreeNode* root) {
if(root==nullptr)return ans;
dfs(0,0,root);
for(auto &[a,b] : mm){
ans.push_back(vector<int>());
while(!b.empty()){
ans.back().push_back(b.top().val);
b.pop();
}
}
return ans;
}
};
复杂度分析
令 n 为数组长度。
var verticalTraversal = function(root) {
let nodes = [];
let res = [];
dfs(root, 0, 0, nodes);
function dfs (root, row, col, nodes) {
if (root === null) return;
nodes.push([col, row, root.val]);
dfs(root.left, row + 1, col - 1, nodes);
dfs(root.right, row + 1, col + 1, nodes);
}
nodes.sort((a, b) => {
if (a[0] !== b[0]) {
return a[0] - b[0];
} else if (a[1] !== b[1]) {
return a[1] - b[1];
} else {
return a[2] - b[2];
}
});
let lastCol = -Number.MAX_VALUE;
for (let node of nodes) {
let col = node[0];
let row = node[1];
let val = node[2];
if (col !== lastCol) {
lastCol = col;
res.push([]);
}
res[res.length - 1].push(val);
}
return res;
};
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def verticalTraversal(self, root: Optional[TreeNode]) -> List[List[int]]:
res = {}
res[0] = [(root.val, 0)]
queue = deque()
queue.append((root, 0, 0))
while queue:
curr, col, row = queue.popleft()
if curr.left:
tc = col-1
queue.append((curr.left, tc, row+1))
if tc in res:
res[tc].append((curr.left.val, row+1))
else:
res[tc] = [(curr.left.val, row+1)]
if curr.right:
tc = col+1
queue.append((curr.right, tc, row+1))
if tc in res:
res[tc].append((curr.right.val, row+1))
else:
res[tc] = [(curr.right.val, row+1)]
ks = sorted(res.keys())
r = []
for k in ks:
r.append(res[k])
for i,item in enumerate(r):
item.sort(key=lambda x: (x[1],x[0]))
r[i] = [v for v, y in item]
return r
使用BFS 搜索,记录下x 和y 坐标,然后再根据y, x, 和val 来排序
Space: O(N)
Time: O(NlogN)
class Solution {
Map<Integer, TreeMap<Integer, List<Integer>>> map = new TreeMap<>(Comparator.naturalOrder());
public List<List<Integer>> verticalTraversal(TreeNode root) {
dfs(root, 0, 0);
List<List<Integer>> vertical = new ArrayList<>();
for (int col : map.keySet()) {
List<Integer> level = new ArrayList<>();
for (List list : map.get(col).values()) {
Collections.sort(list);
level.addAll(list);
}
vertical.add(level);
}
return vertical;
}
public void dfs(TreeNode root, int col, int row) {
if (root == null) return;
map.putIfAbsent(col, new TreeMap<>());
map.get(col).putIfAbsent(row, new ArrayList<>());
map.get(col).get(row).add(root.val);
dfs(root.left, col - 1 , row + 1);
dfs(root.right, col + 1, row + 1);
return;
}
}
class Solution:
def verticalTraversal(self, root: TreeNode) -> List[List[int]]:
nodes = list()
def dfs(node: TreeNode, row: int, col: int) -> None:
if not node:
return
nodes.append((col, row, node.val))
dfs(node.left, row + 1, col - 1)
dfs(node.right, row + 1, col + 1)
dfs(root, 0, 0)
nodes.sort()
ans, lastcol = list(), float("-inf")
for col, row, value in nodes:
if col != lastcol:
lastcol = col
ans.append(list())
ans[-1].append(value)
return ans
质朴的双层哈希表+排序,双层哈希表第一层的键是col,第二层的键是row
DFS遍历二叉树,遍历时记录row和col,将val记录在双层哈希表中。遍历结束后,先按键col排序,再在每个col里按键row排序,最后在每个row里按值排序。
from typing import List, Dict
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
class Solution:
def __init__(self):
self.node_dict = dict()
def verticalTraversal(self, root: TreeNode) -> List[List[int]]:
self.ver_traversal(root, 0, 0)
self.node_dict = dict(sorted(self.node_dict.items(), key=lambda x: x[0]))
ans = []
for col in self.node_dict:
self.node_dict[col] = dict(sorted(self.node_dict[col].items(), key=lambda x: x[0]))
col_temp = []
for row in self.node_dict[col]:
self.node_dict[col][row].sort()
col_temp += self.node_dict[col][row]
ans.append(col_temp)
return ans
def ver_traversal(self, root: TreeNode, row, col) -> Dict:
if not root:
return None
# node_dict是一个双层字典,第一层的键是col,第二层的键是row
if col not in self.node_dict:
self.node_dict[col] = dict()
if row not in self.node_dict[col]:
self.node_dict[col][row] = list()
self.node_dict[col][row].append(root.val)
if root.left:
self.ver_traversal(root.left, row+1, col-1)
if root.right:
self.ver_traversal(root.right, row+1, col+1)
思路:DFS+哈希表
class Solution {
/**
分析:
- 对树进行遍历,这里使用DFS,前序遍历
- 对y坐标,x坐标,节点值进行依次排序,java使用Collection集合类排序
- 以 Y:[X :[val1,val2,...]]为模型,使用哈希表数据结构
*/
// 定义数据结构--哈希表Y:[X :[val1,val2,...]]
Map<Integer,Map<Integer,List<Integer>>> hashMap = new HashMap<>();
public List<List<Integer>> verticalTraversal(TreeNode root) {
// 初始坐标是 (0,0)
dfs(root,0,0);
// 定义所需要的结果集 ---》[val1,val2,...]
List<List<Integer>> res = new ArrayList<>() ;
// 定义Y坐标的临时储存结果,这里使用hashMap.keySet(),生成hashMap所有键值
List<Integer> pos_Y = new ArrayList<>(hashMap.keySet());
// 调用Collections集合的sort函数,进行排序
Collections.sort(pos_Y);
// 遍历pos_Y其中的值,开启逐层拆分
for(Integer i:pos_Y){
// 定义临时数据 --[val1,val2,...]
List<Integer> temp = new ArrayList<>();
// 定义X坐标的临时储存结果,这里使用hashMap.keySet(),生成hashMap键值
List<Integer> pos_X = new ArrayList<>(hashMap.get(i).keySet());
// 调用Collections集合的sort函数,进行排序
Collections.sort(pos_X);
// 遍历pos_X其中的值,开启逐层拆分
for(Integer j :pos_X){
List<Integer> values = hashMap.get(i).get(j);
// 调用Collections集合的sort函数,进行排序(这是对node节点中的值排序了)
Collections.sort(values);
// 排序结束,那么就应该添加到temp集中,由于可能是多个值,所以调用addAll
temp.addAll(values);
}
// 最内层的temp集收集好values值后,应该添加到res结果集中
res.add(temp);
}
// 最后返回结果集
return res;
}
// 前序遍历 传入坐标值x,y
private void dfs(TreeNode root,int x,int y){
if(root==null){
//递归出口
return ;
}
// 前序遍历 主逻辑
// 先判断是否包含Y坐标
if(!hashMap.containsKey(y)){
// 没有就将y添加进去
hashMap.put(y,new HashMap<>());
}
// 后判断是否包含Y坐标中是否有x坐标
if(!hashMap.get(y).containsKey(x)){
// 没有就将x添加进去
hashMap.get(y).put(x,new ArrayList<>());
}
// 将root节点中的值储存到hashMap中
hashMap.get(y).get(x).add(root.val);
// 左右子树遍历
dfs(root.left,x+1,y-1);
dfs(root.right,x+1,y+1);
}
}
时间复杂度:O(NlogN) 空间复杂度:O(N)
因为要按纵轴顺序输出,所以用哈希表来记录同一纵坐标的节点,并且排序后输出二维数组。 然后没跑过,发现题目还要求纵坐标和横坐标都相同的时候需要排序。。。所以哈希表里还得再嵌套一层哈希表,记录同一横坐标的节点。
/**
* @param {TreeNode} root
* @return {number[][]}
*/
var verticalTraversal = function(root) {
const yMap = new Map(); // { y => { x => [val1, val2, ...] } }
function dfs(root, x, y) {
if (!root) {
return null;
}
if (!yMap.has(y)) {
yMap.set(y, new Map());
}
xMap = yMap.get(y);
if (!xMap.has(x)) {
xMap.set(x, []);
}
xMap.get(x).push(root.val);
dfs(root.left, x + 1, y - 1);
dfs(root.right, x + 1, y + 1);
}
dfs(root, 0, 0);
const ySorted = [...yMap.keys()].sort((n1, n2) => {
return n1 - n2;
});
const ans = [];
for (const y of ySorted) {
const vals = []
xMap = yMap.get(y);
const xSorted = [...xMap.keys()].sort((n1, n2) => {
return n1 - n2;
});
for (const x of xSorted) {
const xVals = xMap.get(x).sort((n1, n2) => {
return n1 - n2;
});
vals.push(...xVals);
}
ans.push(vals);
}
return ans;
};
TC: O(nlogn) SC: O(h)
为结点设置坐标 按照横坐标分组
class Solution {
public:
struct node
{
int val;
int x;
int y;
node(int v,int X,int Y):val(v),x(X),y(Y){};
};
vector<node> a;
int minx=1000000,maxx=-1000000;
void fn(TreeNode *root,int x,int y)
{
if(!root)
return;
a.push_back(node(root->val,x,y));
if(x<minx)
minx=x;
if(x>maxx)
maxx=x;
fn(root->left,x-1,y+1);
fn(root->right,x+1,y+1);
}
static bool cmp(node a,node b)
{
if(a.x^b.x)
return a.x<b.x;
if(a.y^b.y)
return a.y<b.y;
return a.val<b.val;
}
vector<vector<int>> verticalTraversal(TreeNode* root) {
fn(root,0,0);
sort(a.begin(),a.end(),cmp);
vector<vector<int>>ans(maxx-minx+1);
for(auto x:a)
{
ans[x.x-minx].push_back(x.val);
}
return ans;
}
};
复杂度分析
var dfs = function (root, nodes, row, col) {
if (!root) return;
nodes.push([root.val, row, col]);
dfs(root.left, nodes, row + 1, col - 1);
dfs(root.right, nodes, row + 1, col + 1);
};
var verticalTraversal = function (root) {
let nodes = [];
dfs(root, nodes, 0, 0);
nodes.sort((a, b) => {
if (a[2] !== b[2]) {
return a[2] - b[2];
} else if (a[1] !== b[1]) {
return a[1] - b[1];
} else {
return a[0] - b[0];
}
});
let ans = [];
let lastCol = -Infinity;
for (let [val, row, col] of nodes) {
if (lastCol !== col) {
lastCol = col;
ans.push([]);
}
ans[ans.length - 1].push(val);
}
return ans;
};
时间:O(nlogn) 空间:O(n)
class Solution {
public:
struct node
{
int val;
int x;
int y;
node(int v,int X,int Y):val(v),x(X),y(Y){};
};
static bool cmp(node a,node b)
{
if(a.x^b.x)
return a.x<b.x;
if(a.y^b.y)
return a.y<b.y;
return a.val<b.val;
}
vector<node> a;
int minx=1000,maxx=-1000;
vector<vector<int>> verticalTraversal(TreeNode* root) {
dfs(root,0,0);
sort(a.begin(),a.end(),cmp);
vector<vector<int>>ans(maxx-minx+1);
for(auto xx:a)
{
ans[xx.x-minx].push_back(xx.val);
}
return ans;
}
void dfs(TreeNode* root,int x,int y)
{
if(root==nullptr)
return;
if(x<minx)
minx=x;
if(x>maxx)
maxx=x;
a.push_back(node(root->val,x,y));
dfs(root->left,x-1,y+1);
dfs(root->right,x+1,y+1);
}
};
``
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
type data struct{col, row, val int}
func verticalTraversal(root *TreeNode) (ans [][]int) {
nodes := []data{}
var dfs func(*TreeNode, int, int)
dfs = func(node *TreeNode, row, col int) {
if node == nil {
return
}
nodes = append(nodes, data{col, row, node.Val})
dfs(node.Left, row+1, col-1)
dfs(node.Right, row+1, col+1)
}
dfs(root, 0, 0)
sort.Slice(nodes, func(i, j int) bool {
a, b := nodes[i], nodes[j]
return a.col < b.col || a.col == b.col && (a.row < b.row || a.row == b.row && a.val < b.val)
})
lastCol := math.MinInt32
for _, node := range nodes {
if node.col != lastCol {
lastCol = node.col
ans = append(ans, nil)
}
ans[len(ans) - 1] = append(ans[len(ans)-1], node.val)
}
return
}
class Solution {
public List<List<Integer>> verticalTraversal(TreeNode root) {
List<List<Integer>> res = new ArrayList<>();
int[] boundary = new int[2];
Map<Integer, TreeMap<Integer, PriorityQueue<Integer>>> map = new HashMap<>();
generateMap(map, root, 0, 0, boundary);
for (int i = boundary[0]; i <= boundary[1]; i++) {
List<Integer> cur = new ArrayList<>();
for (Map.Entry<Integer, PriorityQueue<Integer>> entry : map.get(i).entrySet()) {
while (!entry.getValue().isEmpty()) cur.add(entry.getValue().poll());
}
res.add(cur);
}
return res;
}
private void generateMap(Map<Integer, TreeMap<Integer, PriorityQueue<Integer>>> map, TreeNode root, int x, int y, int[] boundary) {
if (root == null) return;
boundary[0] = Math.min(x, boundary[0]);
boundary[1] = Math.max(x, boundary[1]);
map.putIfAbsent(x, new TreeMap<>());
map.get(x).putIfAbsent(y, new PriorityQueue<>());
map.get(x).get(y).add(root.val);
generateMap(map, root.left, x - 1, y + 1, boundary);
generateMap(map, root.right, x + 1, y + 1, boundary);
}
}
先抄作业mark
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} root
* @return {number[][]}
*/
var verticalTraversal = function(root) {
const map = new Map();
function cal(node, depth, col) {
if (!map.get(col)) map.set(col, new Map());
if (!map.get(col).get(depth)) map.get(col).set(depth, []);
map.get(col).get(depth).push(node.val);
if (node.left) {
cal(node.left, depth + 1, col - 1);
}
if (node.right) {
cal(node.right, depth + 1, col + 1);
}
}
cal(root, 1, 0);
const res = [];
Array.from(map.keys()).sort((a, b) => a - b).forEach((col) => {
const colTemp = [];
Array.from(map.get(col).keys()).sort((a, b) => a - b).forEach(depth => {
colTemp.push(...map.get(col).get(depth).sort((a,b) => a-b));
});
res.push(colTemp);
})
return res;
};
DFS and hash table, figure out how to design the hast table is the key.
class Solution:
def verticalTraversal(self, root: Optional[TreeNode]) -> List[List[int]]:
memo = collections.defaultdict(lambda: collections.defaultdict(list))
res = []
self.helper(memo, root, 0, 0)
for col in sorted(memo):
temp = []
for row in sorted(memo[col]):
temp += sorted(memo[col][row])
res.append(temp)
return res
def helper(self, memo, node, row, col):
if not node: return
memo[col][row].append(node.val)
if node.left: self.helper(memo, node.left, row+1, col-1)
if node.right: self.helper(memo, node.right, row+1, col+1)
Space: O(N) Time: O(NlogN)
class Solution {
TreeMap<Integer, PriorityQueue<int[]>> map;
public List<List<Integer>> verticalTraversal(TreeNode root) {
map = new TreeMap<>();
List<List<Integer>> res = new ArrayList<>();
dfs(root, 0, 0);
for(Integer key: map.keySet()) {
PriorityQueue<int[]> queue = map.get(key);
List<Integer> list = new ArrayList<>();
while (!queue.isEmpty()) {
list.add(queue.poll()[1]);
}
res.add(list);
}
return res;
}
public void dfs(TreeNode node, int row, int col) {
if(node != null) {
PriorityQueue<int[]> pq = null;
if(!map.containsKey(col)) {
pq = new PriorityQueue<>(new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
if(o1[0] == o2[0]) {
return o1[1] - o2[1];
}
return o1[0] - o2[0];
}
});
map.put(col, pq);
}else {
pq = map.get(col);
}
pq.offer(new int[]{row, node.val});
dfs(node.left, row + 1, col - 1);
dfs(node.right, row + 1, col + 1);
}
}
}
时间复杂度: treeMap以及堆的排序插入时间均为log(n) 遍历节点所需要的时间为O(n) 总体时间复杂度为:O(nlogn) 空间复杂度: 迭代所需要的栈空间以及treeMap维护的空间均为O(n)
class Solution {
public:
vector<vector<int>> verticalTraversal(TreeNode* root) {
vector<tuple<int, int, int>> nodes;
function<void(TreeNode*, int, int)> dfs = [&](TreeNode* node, int row, int col) {
if (!node) {
return;
}
nodes.emplace_back(col, row, node->val);
dfs(node->left, row + 1, col - 1);
dfs(node->right, row + 1, col + 1);
};
dfs(root, 0, 0);
sort(nodes.begin(), nodes.end());
vector<vector<int>> ans;
int lastcol = INT_MIN;
for (const auto& [col, row, value]: nodes) {
if (col != lastcol) {
lastcol = col;
ans.emplace_back();
}
ans.back().push_back(value);
}
return ans;
}
};
参考学习
var verticalTraversal = function (root) {
const map = new Map();
const getIdx = function dfs(root, i, j) {
if (!root) return;
if (!map.has(j)) map.set(j, new Map());
if (!map.get(j).has(i)) map.get(j).set(i, []);
map.get(j).get(i).push(root.val);
dfs(root.left, i + 1, j - 1);
dfs(root.right, i + 1, j + 1);
};
getIdx(root, 0, 0);
const MAX = 1000,
resArr = [];
for (let i = -MAX; i <= MAX && resArr.length <= map.size; ++i) {
if (!map.has(i)) continue;
resArr.push([]);
for (let j = -MAX, curM = map.get(i); j <= MAX; ++j) {
if (curM.has(j)) {
resArr[resArr.length - 1].push(...curM.get(j).sort((a, b) => a - b));
}
}
}
return resArr;
};
思路:自己想的,还没看题解,应该是常规做法。
row
,col
坐标,并把这些数据放到一个 hash table。col
为key 的另外一个OrderedDict
, value 为一个当前包含node的(row, val)
的list。OrderedDict
的 key 排序感觉搞复杂了,需要学习
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution(object):
def verticalTraversal(self, root):
"""
:type root: TreeNode
:rtype: List[List[int]]
"""
dic = {}
self.dfs(root, 0, 0, dic)
ans = collections.OrderedDict()
queue = collections.deque()
queue.append(root)
while queue:
N = len(queue)
for _ in range(N):
cur = queue.popleft()
if cur.left:
queue.append(cur.left)
if cur.right:
queue.append(cur.right)
row, col, val = dic[cur]
if col in ans:
ans[col].append((row, val))
else:
ans[col] = [(row, val)]
ret = list(v for i,v in sorted(ans.items(), key=lambda x:x[0]))
for i in ret:
i.sort(key=lambda x:x[1])
for i in ret:
i.sort(key=lambda x:x[0])
return [[v for i,v in x] for x in ret]
def dfs(self, root, row, col, dic):
if not root:
return None
dic[root] = (row, col, root.val)
self.dfs(root.left, row+1, col-1, dic)
self.dfs(root.right, row+1, col+1, dic)
return dic
Time: DFS+BFS+Sort. O(nlogn) Space: 两个n长度的dictionary,O(n)
var verticalTraversal = function(root) {
if(!root) return [];
let map = {};
deepTree(root,0,0);
function deepTree(root,x,y){
if(!root) return ;
x in map || (map[x] = []);
map[x].push([y,root.val]);
deepTree(root.left,x-1,y-1);
deepTree(root.right,x+1,y-1);
}
let sorted = Object.keys(map)
.sort((a, b) => +a - +b)
.map((key) => map[key]);
// 再给 x 坐标相同的每组节点坐标分别排序
sorted = sorted.map((g) => {
g.sort((a, b) => {
// y 坐标相同的,按节点值升序排
if (a[0] === b[0]) return a[1] - b[1];
// 否则,按 y 坐标降序排
else return b[0] - a[0];
});
// 把 y 坐标去掉,返回节点值
return g.map((el) => el[1]);
});
return sorted;
};
Use a map to store the values at each column, use the column number as key and another map as value. For the inner map, use row number as key and a vector as value, the vector store all the values for that <row, column>. After we traversed the whole tree and stored the values in the map, we iterate throught the map and append the values to the result.
class Solution {
public:
void traverse(TreeNode* root, map<int, map<int, vector<int>>>& mapper, int row, int col) {
if (root) {
mapper[col][row].push_back(root->val);
traverse(root->left, mapper, row + 1, col - 1);
traverse(root->right, mapper, row + 1, col + 1);
}
}
vector<vector<int>> verticalTraversal(TreeNode* root) {
map<int, map<int, vector<int>>> mapper;
vector<vector<int>> result;
traverse(root, mapper, 0, 0);
for (auto it = mapper.begin(); it != mapper.end(); it++) {
vector<int> tmp;
for (auto itl = it->second.begin(); itl != it->second.end(); itl++) {
sort(itl->second.begin(), itl->second.end());
tmp.insert(tmp.end(), itl->second.begin(), itl->second.end());
}
result.push_back(tmp);
}
return result;
}
};
O(n), we visit each node just once. (Technically it would be O(nlogk) with k being the number of nodes that have the same row and column index)
O(n), we need extra space to store the map.
987. 二叉树的垂序遍历
入选理由
暂无
题目地址
https://leetcode-cn.com/problems/vertical-order-traversal-of-a-binary-tree
前置知识
题目描述
对位于 (X, Y) 的每个结点而言,其左右子结点分别位于 (X-1, Y-1) 和 (X+1, Y-1)。
把一条垂线从 X = -infinity 移动到 X = +infinity ,每当该垂线与结点接触时,我们按从上到下的顺序报告结点的值(Y 坐标递减)。
如果两个结点位置相同,则首先报告的结点值较小。
按 X 坐标顺序返回非空报告的列表。每个报告都有一个结点值列表。
示例 1:
输入:[3,9,20,null,null,15,7] 输出:[[9],[3,15],[20],[7]] 解释: 在不丧失其普遍性的情况下,我们可以假设根结点位于 (0, 0): 然后,值为 9 的结点出现在 (-1, -1); 值为 3 和 15 的两个结点分别出现在 (0, 0) 和 (0, -2); 值为 20 的结点出现在 (1, -1); 值为 7 的结点出现在 (2, -2)。 示例 2:
输入:[1,2,3,4,5,6,7] 输出:[[4],[2],[1,5,6],[3],[7]] 解释: 根据给定的方案,值为 5 和 6 的两个结点出现在同一位置。 然而,在报告 "[1,5,6]" 中,结点值 5 排在前面,因为 5 小于 6。
提示:
树的结点数介于 1 和 1000 之间。 每个结点值介于 0 和 1000 之间。