Open azl397985856 opened 2 years ago
DFS + 哈希表+ 排序
class Solution {
Map<TreeNode, int[]> map = new HashMap<>(); // col, row, val
public List<List<Integer>> verticalTraversal(TreeNode root) {
map.put(root, new int[]{0, 0, root.val});
dfs(root);
List<int[]> list = new ArrayList<>(map.values());
Collections.sort(list, (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];
});
int n = list.size();
List<List<Integer>> ans = new ArrayList<>();
for (int i = 0; i < n; ) {
int j = i;
List<Integer> tmp = new ArrayList<>();
while (j < n && list.get(j)[0] == list.get(i)[0]) tmp.add(list.get(j++)[2]);
ans.add(tmp);
i = j;
}
return ans;
}
void dfs(TreeNode root) {
if (root == null) return ;
int[] info = map.get(root);
int col = info[0], row = info[1], val = info[2];
if (root.left != null) {
map.put(root.left, new int[]{col - 1, row + 1, root.left.val});
dfs(root.left);
}
if (root.right != null) {
map.put(root.right, new int[]{col + 1, row + 1, root.right.val});
dfs(root.right);
}
}
}
采用hashmap存储DFS遍历的结果,根据col,row,val的顺序自定义collections.sort的排序方式
/**
* 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 {
HashMap<TreeNode,int[]> map = new HashMap<>();
public List<List<Integer>> verticalTraversal(TreeNode root) {
map.put(root,new int[]{0,0,root.val});
List<List<Integer>> res = new ArrayList<>();
dfs(root);
List<int[]> list = new ArrayList<>(map.values());
Collections.sort(list,(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];
});
int n = list.size();
for(int i = 0; i < n;){
int j = i;
List<Integer> tmp = new ArrayList<>();
while(j < n && list.get(j)[0]==list.get(i)[0]) tmp.add(list.get(j++)[2]);
res.add(tmp);
i = j;
}
return res;
}
private void dfs(TreeNode root){
if(root==null) return;
int[] info = map.get(root);
int col = info[0], row = info[1];
if(root.left != null){
map.put(root.left,new int[]{col-1,row+1,root.left.val});
dfs(root.left);
}
if(root.right != null){
map.put(root.right,new int[]{col+1,row+1,root.right.val});
dfs(root.right);
}
}
}
时间复杂度 O(nlogn) 空间复杂度O(n)
class Solution:
def verticalTraversal(self, root: Optional[TreeNode]) -> List[List[int]]:
hashmap = defaultdict(list)
leftcol = rightcol = 0
stack = []
stack.append((root, 0, 0))
while stack:
node, row, col = stack.pop()
hashmap[col].append((row, node.val))
leftcol = min(leftcol, col)
rightcol = max(rightcol, col)
if node.left:
stack.append((node.left, row + 1, col - 1))
if node.right:
stack.append((node.right, row + 1, col + 1))
ans = []
for col in range(leftcol, rightcol + 1):
l = []
for row, value in sorted(hashmap[col]):
l.append(value)
ans.append(l)
return ans
Time complexity O(NlogN) Space complexity O(N)
code
public List<List<Integer>> verticalTraversal(TreeNode root) {
List<int[]> nodes = new ArrayList<>();
dfs(root, 0, 0, nodes);
// 定义排序方式
// 按照列号优先,之后是行号,最后是值从小到大
Collections.sort(nodes, new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
if (o1[0] != o2[0]) {
return o1[0] - o2[0];
} else if (o1[1] != o2[1]) {
return o1[1] - o2[1];
} else {
return o1[2] - o2[2];
}
}
});
// 按列生成返回链表
List<List<Integer>> ans = new ArrayList<>();
int size = 0;
int lastcol = Integer.MIN_VALUE;
for (int[] node : nodes) {
int col = node[0], row = node[1], value = node[2];
if (col != lastcol) {
lastcol = col;
ans.add(new ArrayList<Integer>());
size++;
}
ans.get(size - 1).add(value);
}
return ans;
}
// dfs并保存每个节点的坐标和值
private void dfs(TreeNode node, int row, int col, List<int[]> nodes) {
if (node == null) {
return;
}
nodes.add(new int[]{col, row, node.val});
dfs(node.left, row + 1, col - 1, nodes);
dfs(node.right, row + 1, col + 1, nodes);
}
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
# 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 vHelper(self, head, tuples, loc, row):
if head:
tuples.append((loc, row, head.val))
self.vHelper(head.left, tuples, loc-1, row+1)
self.vHelper(head.right, tuples, loc+1, row+1)
def verticalTraversal(self, root: Optional[TreeNode]) -> List[List[int]]:
if not root:
return []
tuples = []
self.vHelper(root, tuples, 0, 0)
tuples.sort()
results = OrderedDict()
for loc, row, value in tuples:
if loc not in results:
results[loc] = [value]
else:
results[loc].append(value)
return results.values()
利用深度遍历
var verticalTraversal = function(root) {
let obj = {};
let arr = [];
let traverseTree = (root, row, col) => {
if (!root) return;
if (!obj[row]) {
obj[row] = {};
}
if (!obj[row][col]) {
obj[row][col] = [root.val];
} else {
obj[row][col].push(root.val);
obj[row][col].sort((a, b) => a - b);
}
traverseTree(root.left, row - 1, col + 1);
traverseTree(root.right, row + 1, col + 1);
};
traverseTree(root, 0, 0);
for (let row in obj) {
let temp = [];
for (let col in obj[row]) {
temp = temp.concat(obj[row][col]);
}
obj[row] = temp;
}
let keys = Object.keys(obj).sort((a, b) => Number(a) - Number(b));
keys.forEach(vv => {
arr.push(obj[vv]);
});
return arr;
};
时间复杂度:O(n)
空间复杂度:O(n)
dfs遍历树,map记录信息,TreeMap保持列和层的键的有序,对每一层的数组排序,再添加到一列中的数组中,最后添加到结果中
class Solution {
public List<List<Integer>> verticalTraversal(TreeNode root) {
map = new TreeMap<>();
dfs(root, 0, 0);
List<List<Integer>> res = new LinkedList<>();
for(Map.Entry<Integer, Map<Integer, List<Integer>>> entry: map.entrySet()) {
Map<Integer, List<Integer>> level = entry.getValue();
// 一层
List<Integer> temp = new ArrayList<>();
for(Map.Entry<Integer, List<Integer>> levelEntry : level.entrySet()) {
List<Integer> list = levelEntry.getValue();
list.sort((a, b) -> {
return a - b;
});
for(int i : list) {
temp.add(i);
}
}
res.add(temp);
}
return res;
}
Map<Integer, Map<Integer, List<Integer>>> map;
private void dfs(TreeNode root, int i, int y) {
if(root == null) {
return;
}
if(!map.containsKey(i)) {
map.put(i, new TreeMap<>());
}
if(!map.get(i).containsKey(y)) {
map.get(i).put(y, new ArrayList<>());
}
map.get(i).get(y).add(root.val);
dfs(root.left, i - 1, y + 1);
dfs(root.right, i + 1, y + 1);
}
}
时间复杂度: O(N)lg(N) 空间复杂度: O(N)
还真就那个深搜
/**
* 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:
map<int, vector<pair<int, int> > > mp;
void dfs(TreeNode* root, int x, int y) {
if (root == nullptr) return;
mp[y].push_back({x, root->val});
dfs(root->left, x + 1, y - 1);
dfs(root->right, x + 1, y + 1);
}
vector<vector<int>> verticalTraversal(TreeNode* root) {
dfs(root, 0, 0);
vector<vector<int> > res;
for (auto& p : mp) {
sort(p.second.begin(), p.second.end());
vector<int> v;
for (auto t : p.second) {
v.push_back(t.second);
}
res.push_back(v);
}
return res;
}
};
class Solution(object):
def verticalTraversal(self, root):
seen = collections.defaultdict(
lambda: collections.defaultdict(list))
def dfs(root, x=0, y=0):
if not root:
return
seen[x][y].append(root.val)
dfs(root.left, x-1, y+1)
dfs(root.right, x+1, y+1)
dfs(root)
ans = []
# x 排序、
for x in sorted(seen):
level = []
# y 排序
for y in sorted(seen[x]):
# 值排序
level += sorted(v for v in seen[x][y])
ans.append(level)
return ans
思路:
使用哈希表,最外层key使用x坐标,第二层key使用y坐标,第二层value使用list保存值(同一坐标可能多个值);
先按照x坐标排序,再按照y排序,最后按照值大小排序;排序过程中,相同x坐标在同一个数组;
步骤:
DFS遍历树,使用哈希表结构保存x,y,值;
java
class Solution {
Map<Integer, Map<Integer, List<Integer>>> xMap = new TreeMap(new MyComparator());
public List<List<Integer>> verticalTraversal(TreeNode root) {
List<List<Integer>> xList = new LinkedList();
int[] coordinate = new int[]{0,0};
//遍历树,将结点坐标按规则保存在Map里
dfs(root,coordinate);
//将
for(Map.Entry entry1 : xMap.entrySet()){
List<Integer> yList = new LinkedList();
Map<Integer,List<Integer>> yMap =(Map<Integer,List<Integer>>) entry1.getValue();
for(Map.Entry entry2 : yMap.entrySet()){
List<Integer> valList = (List<Integer>)entry2.getValue();
Collections.sort(valList);
yList.addAll(valList);
}
xList.add(yList);
}
return xList;
}
class MyComparator implements Comparator<Integer>{
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
}
public void dfs(TreeNode root,int[] coordinate){
if(root == null){
return;
}
Map<Integer,List<Integer>> yMap;
if(xMap.containsKey(coordinate[0])){
yMap = xMap.get(coordinate[0]);
List<Integer> valList;
if(yMap.containsKey(coordinate[1])){
valList = yMap.get(coordinate[1]);
valList.add(root.val);
}else{
valList = new LinkedList();
valList.add(root.val);
yMap.put(coordinate[1],valList);
}
}else{
yMap = new TreeMap(new MyComparator());
List<Integer> valList = new LinkedList();
valList.add(root.val);
yMap.put(coordinate[1],valList);
xMap.put(coordinate[0],yMap);
}
dfs(root.left,new int[]{coordinate[0]-1,coordinate[1]+1});
dfs(root.right,new int[]{coordinate[0]+1,coordinate[1]+1});
}
}
时间:O(nlogn),瓶颈在排序,所有元素都排序;(疑问:双循环遍历map不是O($n^2$)?)
空间:O();递归栈O(n),map保存O(n);
class Solution(object): def verticalTraversal(self, root): nodes = list()
def dfs(node, row, col):
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
class Solution: def verticalTraversal(self, root: TreeNode) -> List[List[int]]: nodes = list()
def dfs(node, row, col):
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
我们可以从根节点开始,对整棵树进行一次遍历,在遍历的过程中使用数组 nodes 记录下每个节点的行号 row,列号 col 以及值 value。在遍历完成后,我们按照 col 为第一关键字升序,row 为第二关键字升序,value 为第三关键字升序,对所有的节点进行排序即可。
在排序完成后,我们还需要按照题目要求,将同一列的所有节点放入同一个数组中。因此,我们可以对 nodes 进行一次遍历,并在遍历的过程中记录上一个节点的列号 lastcol。如果当前遍历到的节点的列号 col 与 lastcol 相等,则将该节点放入与上一个节点相同的数组中,否则放入不同的数组中。
class Solution {
public List<List<Integer>> verticalTraversal(TreeNode root) {
List<int[]> nodes = new ArrayList<int[]>();
dfs(root, 0, 0, nodes);
Collections.sort(nodes, new Comparator<int[]>() {
public int compare(int[] tuple1, int[] tuple2) {
if (tuple1[0] != tuple2[0]) {
return tuple1[0] - tuple2[0];
} else if (tuple1[1] != tuple2[1]) {
return tuple1[1] - tuple2[1];
} else {
return tuple1[2] - tuple2[2];
}
}
});
List<List<Integer>> ans = new ArrayList<List<Integer>>();
int size = 0;
int lastcol = Integer.MIN_VALUE;
for (int[] tuple : nodes) {
int col = tuple[0], row = tuple[1], value = tuple[2];
if (col != lastcol) {
lastcol = col;
ans.add(new ArrayList<Integer>());
size++;
}
ans.get(size - 1).add(value);
}
return ans;
}
public void dfs(TreeNode node, int row, int col, List<int[]> nodes) {
if (node == null) {
return;
}
nodes.add(new int[]{col, row, node.val});
dfs(node.left, row + 1, col - 1, nodes);
dfs(node.right, row + 1, col + 1, nodes);
}
}
时间复杂度:O(N)
空间复杂度:O(N)
DFS
:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* 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) {
List<int[]> list = new ArrayList<>();
dfs(root, 0, 0, list);
List<List<Integer>> ans = new ArrayList<>();
Collections.sort(list, new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
if (o1[0] != o2[0]) return o1[0] - o2[0];
else if (o1[1] != o2[1]) return o1[1] - o2[1];
else if (o1[2] != o2[2]) return o1[2] - o2[2];
return 0;
}
});
int lastCol = Integer.MAX_VALUE;
int size = 0;
for (int[] lst : list) {
int col = lst[0], row = lst[1], val = lst[2];
if (lastCol != col) {
ans.add(new ArrayList<>());
lastCol = col;
size++;
}
ans.get(size - 1).add(val);
}
return ans;
}
public void dfs(TreeNode root, int row, int col, List<int[]> list) {
if (root == null) return;
list.add(new int[]{col, row, root.val});
dfs(root.left, row + 1, col - 1, list);
dfs(root.right, row + 1, col + 1, list);
}
}
DFS
是O(n),排序是O(nlogn),最后的遍历是O(n)/**
* 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:
map<int, vector<vector<int>>> map;
vector<vector<int>> verticalTraversal(TreeNode* root) {
dfs(root, 0, 0);
vector<vector<int>> res;
for (auto& [k, v] : map) {
sort(v.begin(), v.end());
vector<int> col;
for (auto& p : v) col.push_back(p[1]);
res.push_back(col);
}
return res;
}
void dfs(TreeNode* root, int x, int y) {
if (!root) return;
map[y].push_back({x, root->val});
dfs(root->left, x + 1, y - 1);
dfs(root->right, x + 1, y + 1);
}
};
class Solution {
List<Location> locationList = new ArrayList<>();
public List<List<Integer>> verticalTraversal(TreeNode root) {
dfs(root, 0, 0);
locationList.sort(null);
List<List<Integer>> list = new ArrayList<>();
List<Integer> tmpList = new ArrayList<>();
tmpList.add(locationList.get(0).val);
for (int i=1; i<locationList.size(); i++) {
Location tmp = locationList.get(i);
Location pre = locationList.get(i-1);
if (tmp.x == pre.x) {
tmpList.add(tmp.val);
}
else {
list.add(new ArrayList<>(tmpList));
tmpList.clear();
tmpList.add(tmp.val);
}
}
list.add(tmpList);
return list;
}
public void dfs(TreeNode root, int x, int y) {
if (root == null) return;
Location location = new Location(root.val, x, y);
locationList.add(location);
dfs(root.left, x-1, y-1);
dfs(root.right, x+1, y-1);
}
}
class Location implements Comparable<Location>{
int val;
int x;
int y;
public Location(int val, int x, int y) {
this.val = val;
this.x = x;
this.y = y;
}
@Override
public int compareTo(Location o) {
if (this.x > o.x) return 1;
else if (this.x == o.x) {
if (this.y < o.y) return 1;
else if (this.y == o.y) {
if (this.val > o.val) return 1;
else if (this.val == o.val) return 0;
else return -1;
}
else return -1;
}
else return -1;
}
}
JavaScript
var verticalTraversal = function(root) {
const nodes = [];
dfs(root, 0, 0, nodes);
nodes.sort((tuple1, tuple2) => {
if (tuple1[0] !== tuple2[0]) {
return tuple1[0] - tuple2[0];
} else if (tuple1[1] !== tuple2[1]) {
return tuple1[1] - tuple2[1];
} else {
return tuple1[2] - tuple2[2];
}
});
const ans = [];
let lastcol = -Number.MAX_VALUE;
for (const tuple of nodes) {
let col = tuple[0], row = tuple[1], value = tuple[2];
if (col !== lastcol) {
lastcol = col;
ans.push([]);
}
ans[ans.length - 1].push(value);
}
return ans;
}
const dfs = (node, row, col, nodes) => {
if (node === null) {
return;
}
nodes.push([col, row, node.val]);
dfs(node.left, row + 1, col - 1, nodes);
dfs(node.right, row + 1, col + 1, nodes);
}
class Solution {
public:
struct Node {
int x, y;
TreeNode *root;
Node() {}
Node(int a, int b, TreeNode *c) : x(a), y(b), root(c) {}
};
vector <vector <int>> ans;
map <int, vector<int>> ss;
vector<vector<int>> verticalTraversal(TreeNode* root) {
if(!root) return ans;
queue <Node> q;
q.push({0, 0, root});
while(!q.empty()) {
int n = q.size();
map <int, vector<int>> tmp; // 临时的 map
for(int i = 0; i < n; i++) {
auto k = q.front();
q.pop();
tmp[k.y].push_back(k.root->val);
if(k.root->left) q.push({k.x + 1, k.y - 1, k.root->left});
if(k.root->right) q.push({k.x + 1, k.y + 1, k.root->right});
}
for(auto &[x, y] : tmp) { // 遍历
sort(y.begin(), y.end()); // 排序
for(auto &c : y) ss[x].push_back(c); // 将节点加入第一个 map(ss) 中
}
tmp.clear();
}
for(auto &[x, y] : ss) {
ans.push_back(y);
}
return ans;
}
};
var verticalTraversal = function(root) {
const nodes = [];
dfs(root, 0, 0, nodes);
nodes.sort((tuple1, tuple2) => {
if (tuple1[0] !== tuple2[0]) {
return tuple1[0] - tuple2[0];
} else if (tuple1[1] !== tuple2[1]) {
return tuple1[1] - tuple2[1];
} else {
return tuple1[2] - tuple2[2];
}
});
const ans = [];
let lastcol = -Number.MAX_VALUE;
for (const tuple of nodes) {
let col = tuple[0], row = tuple[1], value = tuple[2];
if (col !== lastcol) {
lastcol = col;
ans.push([]);
}
ans[ans.length - 1].push(value);
}
return ans;
}
const dfs = (node, row, col, nodes) => {
if (node === null) {
return;
}
nodes.push([col, row, node.val]);
dfs(node.left, row + 1, col - 1, nodes);
dfs(node.right, row + 1, col + 1, nodes);
}
class Solution {
public List<List
Queue<TreeNode>queue = new LinkedList<>();
Queue<Integer> x = new LinkedList<>();
queue.add(root);
x.add(0);
Map<Integer,List<Integer>> map = new HashMap<>();
while(!queue.isEmpty()){
int len = queue.size();
Map<Integer,List<Integer>> tmp = new HashMap<>();
for(int i = 0; i < len; i++){
TreeNode curr = queue.remove();
int currX = x.remove();
tmp.putIfAbsent(currX,new ArrayList<Integer>());
tmp.get(currX).add(curr.val);
if(curr.left != null){
queue.add(curr.left);
x.add(currX - 1);
}
if(curr.right != null){
queue.add(curr.right);
x.add(currX + 1);
}
}
for(Integer key : tmp.keySet()){
map.putIfAbsent(key, new ArrayList<Integer>());
Collections.sort(tmp.get(key));
map.get(key).addAll(tmp.get(key));
}
}
List<Integer> list = new ArrayList<>(map.keySet());
Collections.sort(list);
List<List<Integer>> res = new ArrayList<>();
for(int key : list){
res.add(map.get(key));
}
return res;
}
}
dfs 遍历,保存每个节点的行,列,值,然后对行,列,值进行排序。最后将处于同一列的节点的值从小到大,保存到结果中。
var verticalTraversal = function(root) {
const nodes = [];
dfs(root, 0, 0, nodes);
nodes.sort((tuple1, tuple2) => {
if (tuple1[0] !== tuple2[0]) {
return tuple1[0] - tuple2[0];
} else if (tuple1[1] !== tuple2[1]) {
return tuple1[1] - tuple2[1];
} else {
return tuple1[2] - tuple2[2];
}
});
const ans = [];
let lastcol = -Number.MAX_VALUE;
for (const tuple of nodes) {
let col = tuple[0], row = tuple[1], value = tuple[2];
if (col !== lastcol) {
lastcol = col;
ans.push([]);
}
ans[ans.length - 1].push(value);
}
return ans;
}
const dfs = (node, row, col, nodes) => {
if (node === null) {
return;
}
nodes.push([col, row, node.val]);
dfs(node.left, row + 1, col - 1, nodes);
dfs(node.right, row + 1, col + 1, nodes);
}
时间复杂度: O(n^2)
空间复杂度: O(n)
主要是解决以下三件事
1、对所有节点遍历并记录其val,x,y
2、对所有节点按规则进行排序
3、将排序后的val根据x分块并输出(输出就是leetcode的事了)
具体的代码里注释已经非常详细了
/**
* 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:
//要解决三件事:
//1、对所有节点遍历并记录其val,x,y
//2、对所有节点按规则进行排序
//3、将排序后的val根据x分块并输出
struct node{
int val; //值
int x; //列col
int y; //行row
node(int value, int col, int row):val(value),x(col),y(row){};
};
int xmax = -1000;
int xmin = 1000; //根据提示给定初始值
vector<node> s; //存储需要的节点信息
void DFS(TreeNode* root, int x, int y){
if(!root) return;
//需要记录列的最小值和最大值方便构造res数组
if(x<xmin) xmin = x;
if(x>xmax) xmax = x;
//记录当前节点的值以及位置信息
//先序遍历
s.push_back(node(root->val,x,y));
DFS(root->left,x-1,y+1);
DFS(root->right,x+1,y+1);
}
//遍历及记录就结束了
static bool cmp(node a, node b){
//如果x不同,则首先按x升序排序
if(a.x != b.x) return a.x<b.x;
//如果x相同,而y不同,则按y升序排序
if(a.y != b.y) return a.y<b.y;
//如果两节点处在同一位置,则按值大小升序排列
return a.val<b.val;
}
vector<vector<int>> verticalTraversal(TreeNode* root) {
//开始走流程
DFS(root,0,0);
sort(s.begin(),s.end(),cmp);
vector<vector<int>> res;
res.resize(xmax-xmin+1);
for(auto cur:s){
res[cur.x - xmin].push_back(cur.val);
}
return res;
}
};
复杂度分析
时间复杂度:O(nlogn) sort产生
空间复杂度:O(n) n为节点数
var verticalTraversal = function(root) {
const pointArr = []
const getTreeNode = (node, nodeX, nodeY) => {
if (node === null) {
return
}
pointArr.push([nodeX, nodeY, node.val])
getTreeNode(node.left, nodeX + 1, nodeY - 1)
getTreeNode(node.right, nodeX + 1, nodeY + 1)
}
getTreeNode(root, 0, 0)
pointArr.sort((left, right) => {
if (left[1] === right[1]) {
if (left[0] === right[0]) {
return left[2] - right[2]
} else {
return left[0] - right[0]
}
} else {
return left[1] - right[1]
}
})
const res = []
let lastPosY = null
for(let i = 0; i < pointArr.length; i++) {
const [posX, posY, val ] = pointArr[i]
if (posY !== lastPosY) {
lastPosY = posY
res.push([])
}
res[res.length - 1].push(val)
}
return res
};
class Solution {
private:
int min_value = 0;
int max_value = 0;
public:
vector<vector<int>> verticalTraversal(TreeNode* root) {
get_left(root, 0);
vector<vector<pair<int, int>>> v(max_value+abs(min_value)+1);
dfs(v, root, 0,0);
vector<vector<int>> res(v.size());
for(int i = 0;i<v.size();i++){
sort(v[i].begin(), v[i].end(), [](const pair<int, int>& p1,const pair<int, int>& p2)->bool{
if(p1.second==p2.second){
return p1.first<p2.first;
}
return p1.second<p2.second;
});
for(int j =0 ;j<v[i].size();j++){
res[i].push_back(v[i][j].first);
}
}
return res;
}
void get_left(TreeNode* root,int left){
if(root == NULL){
return;
}
if(root->left!=NULL){
min_value = min(min_value,left-1);
}
if(root->right!=NULL){
max_value = max(max_value,left+1);
}
get_left(root->left, left-1);
get_left(root->right, left+1);
}
void dfs(vector<vector<pair<int, int>>>& res,TreeNode* root,int level,int depth){
if(root == NULL){
return;
}
dfs(res, root->left, level-1,depth+1);
res[level+abs(min_value)].emplace_back(root->val,depth);
dfs(res, root->right, level+1,depth+1);
}
};
# DFS
class Solution(object):
def verticalTraversal(self, root):
"""
:type root: TreeNode
:rtype: List[List[int]]
"""
out = []
def dfs(root, col, row):
if not root:
return None
out.append((col, row, root.val))
dfs(root.left, col - 1, row + 1)
dfs(root.right, col + 1, row + 1)
dfs(root, 0, 0)
out.sort()
res = []
ind = float("-inf")
for node in out:
if ind != node[0]:
ind = node[0]
res.append(list())
res[-1].append(node[2])
return res
时间复杂度:O(nlogn)
空间复杂度:O(n)
DFS
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);
}
};
复杂度分析 -时间复杂度:$O(NlogN)$,其中 N 为树的节点总数。 -空间复杂度:$O(N)$,其中 N 为树的节点总数。
通过bfs遍历树,节点的左子树列坐标-1,右子树列坐标+1,每次向下一层行坐标+1。然后将每个节点的值与行,列坐标保存。再进行排序。(本来我是自己写了排序,看了官方题解后,感觉官方的比较简洁,故采用了官方使用的Collections工具类进行排序)
public class Day18 {
public List<List<Integer>> verticalTraversal(TreeNode root) {
List<List<Integer>> list = new ArrayList<>();
if(root.left==null && root.right==null){
List<Integer> col =new ArrayList<>();
col.add(root.val);
list.add(col);
return list;
}
traversal(root,0,0);
Collections.sort(res, new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
if(o1[0]!=o2[0])
return o1[0]-o2[0];
if(o1[1]!=o2[1]){
return o1[1]-o2[1];
}
return o1[2]-o2[2];
}
});
int index = Integer.MIN_VALUE;
for (int i = 0; i < res.size(); i++) {
int[] temp = res.get(i);//temp[0]-列 temp[1]-行 temp[2]-值
if(temp[0]>index){//之前 未录入 此列
index = temp[0];
List<Integer> col =new ArrayList<>();
col.add(temp[2]);
list.add(col);
} else {
List<Integer> col = list.get(list.size()-1) ;
col.add(temp[2]);
}
}
return list;
}
List<int[]> res = new ArrayList<>();
/**
*
* @param node
* @param x
* @param y
*/
public void traversal(TreeNode node,int x,int y){
if(node==null){
return;
}
int[] temp= new int[]{x,y,node.val};//x==列 y:行
res.add(temp);
traversal(node.left,x-1,y+1);
traversal(node.right,x+1,y+1);
}
}
时间复杂度:O(nlogN)使用了Collections.sort()方法进行排序,故时间复杂度为O(nlogn)
空间复杂度:O(n)
https://leetcode-cn.com/problems/vertical-order-traversal-of-a-binary-tree
思路:
def verticalTraversal(self, root: TreeNode) -> List[List[int]]:
nodes = list()
def DFS(col,row,node):
if not node:
return
nodes.append((col,row,node.val))
DFS(col-1,row+1,node.left)
DFS(col + 1,row + 1,node.right)
# 两次排序,从左到右边,从上到下
DFS(0,0,root)
nodes.sort() #因为是依次按照索引进行排序,所以位置相同时即保证Value值从上到下
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
复杂度:
// 12-29 cpp
#include <map>
class Solution {
public:
map<int, vector<pair<int, int> > >mp; // mp(y, x, val)
void dfs(TreeNode * root, int x, int y) {
if (root == NULL) return;
mp[y].push_back({x, root->val});
if (root->left) dfs(root->left, x + 1, y - 1);
if (root->right) dfs(root->right, x + 1, y + 1);
}
vector<vector<int>> verticalTraversal(TreeNode* root) {
dfs (root, 0, 0);
vector<vector<int>> ans;
for (auto &p : mp) {
sort(p.second.begin(), p.second.end());
vector<int> v;
for (auto &q : p.second) {
v.push_back(q.second);
}
ans.push_back(v);
}
return ans;
}
};
/**
* @param {TreeNode} root
* @return {number[][]}
*/
var verticalTraversal = function (root) {
if (!root) return [];
// 坐标集合以 x 坐标分组
const pos = {};
// dfs 遍历节点并记录每个节点的坐标
dfs(root, 0, 0);
// 得到所有节点坐标后,先按 x 坐标升序排序
let sorted = Object.keys(pos)
.sort((a, b) => +a - +b)
.map((key) => pos[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;
// *********************************
function dfs(root, x, y) {
if (!root) return;
x in pos || (pos[x] = []);
// 保存坐标数据,格式是: [y, val]
pos[x].push([y, root.val]);
dfs(root.left, x - 1, y - 1);
dfs(root.right, x + 1, y - 1);
}
};
时间复杂度:O(NlogN)O(NlogN),其中 N 为树的节点总数。
空间复杂度:O(N)O(N),其中 N 为树的节点总数
先 DFS 遍历,再按照题意排序,最后根据列整理出答案
/**
* 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 nodes = [];
dfs(root, 0, 0, nodes);
nodes.sort((a, b) => {
if (a.col !== b.col) {
// 列从左到右
return a.col - b.col;
} else if (a.row !== b.row) {
// 行从上到下
return a.row - b.row;
} else {
// 同行同列,按值从小到大
return a.val - b.val;
}
})
// 按照列来整理答案
const res = [];
let lastCol = Number.MIN_SAFE_INTEGER;
for (const node of nodes) {
const { col, val } = node;
if (col !== lastCol) {
lastCol = col;
res.push([]);
}
res[res.length - 1].push(val);
}
return res;
function dfs(root, row, col) {
if (!root) {
return;
}
nodes.push({
col,
row,
val: root.val
})
dfs(root.left, row + 1 , col - 1);
dfs(root.right, row + 1, col + 1);
}
};
时间:O(N) 空间:O(N)
LeetCode题目连接: 987. 二叉树的垂序遍历 https://leetcode-cn.com/problems/vertical-order-traversal-of-a-binary-tree/
常规的BFS层序遍历,需要额外加入节点的位置信息(行列),并按照位置信息和节点值进行排序。
BFS层序遍历:
# 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 not root:
return []
res = []
deque = collections.deque()
deque.append((root, 0))
while deque:
tmp = collections.defaultdict(list)
for _ in range(len(deque)):
node, j = deque.popleft()
tmp[j].append(node.val)
if node.left:
deque.append((node.left, j-1))
if node.right:
deque.append((node.right, j+1))
for k in tmp:
res[k].extend(sorted(tmp[k]))
return [res[i] for i in range(min(res.keys()), max(res.keys())+1)]
复杂度分析
考虑用数据结构存储节点的col,row,value,为方便插入可以使用哈希表,由于是垂序遍历,以col作为key。通过深度优先遍历,将遍历的节点存入哈希表。对哈希表进行排序,先将其按col升序排序,再按row升序排序,最后将其映射到value。
var verticalTraversal = function(root) {
let pos = {};
dfs(root, 0, 0);
// 按照从小到大对col进行排序,并将其映射成[[row, value]]
let sorted = Object.keys(pos)
.sort((a, b) => a - b)
.map(key => pos[key]);
// 按row从小到大进行排序,并将其映射成value
sorted = sorted.map(col => {
col.sort((a, b) => {
if(a[0] === b[0]) return a[1] - b[1];
else return a[0] - b[0];
})
return col.map(el => el[1]);
})
function dfs(root, col, row){
if(!root) return;
(col in pos) || (pos[col] = []);
pos[col].push([row, root.val]);
dfs(root.left, col - 1, row + 1);
dfs(root.right, col + 1, row + 1);
return;
}
return sorted;
};
复杂度分析
https://leetcode-cn.com/problems/vertical-order-traversal-of-a-binary-tree/
DFS 求出每个点 的坐标,存入哈希表,然后使用优先队列进行排序
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> > ss;
vector <vector<int>> ans;
void dfs(int x, int y, TreeNode *root) {
if(!root) return ;
ss[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) return ans;
dfs(0, 0, root);
for(auto &[x, y] : ss) {
ans.push_back(vector<int>());
while(!y.empty()) {
ans.back().push_back(y.top().val);
y.pop();
}
}
return ans;
}
};
复杂度分析
虽然标为hard,其实核心还考察数的遍历,比较不好处理的其实是对遍历的结果进行排序。
class Solution { public List<List<Integer>> verticalTraversal(TreeNode root) { if(root==null)return null; List<int[]> list = new ArrayList<>(); fun(root,0,0,list); Collections.sort(list,new Comparator<int[]>(){ public int compare(int[] tuple1, int[] tuple2) { if (tuple1[0] != tuple2[0]) { return tuple1[0] - tuple2[0]; } else if (tuple1[1] != tuple2[1]) { return tuple1[1] - tuple2[1]; } else { return tuple1[2] - tuple2[2]; } } }); List<List<Integer>> res = new ArrayList<>(); int size = 0; int lastcol = Integer.MIN_VALUE; for (int[] tuple : list) { int col = tuple[0], row = tuple[1], value = tuple[2]; if (col != lastcol) { lastcol = col; res.add(new ArrayList<Integer>()); size++; } res.get(size - 1).add(value); } return res; } public void fun(TreeNode root ,int col, int row, List<int[]> list){ if(root == null)return; int[] temp = new int[3];//分别为 列 行 值 temp[0] = col; temp[1] = row; temp[2] = root.val; list.add(temp); fun(root.left,col-1,row+1,list); fun(root.right,col+1,row+1,list); } }
时间复杂度:O(nlogn)
空间复杂度:O(n)
class Solution {
public List<List<Integer>> verticalTraversal(TreeNode root) {
List<int[]> nodes = new ArrayList<int[]>();
dfs(root, 0, 0, nodes);
Collections.sort(nodes, new Comparator<int[]>() {
public int compare(int[] tuple1, int[] tuple2) {
if (tuple1[0] != tuple2[0]) {
return tuple1[0] - tuple2[0];
} else if (tuple1[1] != tuple2[1]) {
return tuple1[1] - tuple2[1];
} else {
return tuple1[2] - tuple2[2];
}
}
});
List<List<Integer>> ans = new ArrayList<List<Integer>>();
int size = 0;
int lastcol = Integer.MIN_VALUE;
for (int[] tuple : nodes) {
int col = tuple[0], row = tuple[1], value = tuple[2];
if (col != lastcol) {
lastcol = col;
ans.add(new ArrayList<Integer>());
size++;
}
ans.get(size - 1).add(value);
}
return ans;
}
public void dfs(TreeNode node, int row, int col, List<int[]> nodes) {
if (node == null) {
return;
}
nodes.add(new int[]{col, row, node.val});
dfs(node.left, row + 1, col - 1, nodes);
dfs(node.right, row + 1, col + 1, nodes);
}
}
C++ Code:
class Solution {
public:
vector<vector<int>> verticalTraversal(TreeNode* root) {
map<int, vector<pair<int, int>>> position;
dfs(root, 0, 0, position);
vector<vector<int>> res;
for(auto& p: position){
sort(p.second.begin(), p.second.end());
vector<int> cur;
for(const pair<int, int>& x: p.second) {
cur.push_back(x.second);
}
res.push_back(cur);
}
return res;
}
private:
void dfs(TreeNode* node, int row, int col, map<int, vector<pair<int, int>>>& position){
if(node == nullptr) {
return;
}
position[col].push_back({row, node->val});
dfs(node->left, row + 1, col - 1, position);
dfs(node->right, row + 1, col + 1, position);
}
};
复杂度分析
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
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
Code:
public class Solution {
public SortedDictionary<int, SortedDictionary<int, List<int>>> dicts;
public List<IList<int>> result;
public IList<IList<int>> VerticalTraversal(TreeNode root) {
result = new List<IList<int>>();
dicts = new SortedDictionary<int, SortedDictionary<int, List<int>>>();
if (root == null)
return result;
DFSHelper(root, 0, 0);
foreach(var colItem in dicts)
{
List<int> colList = new List<int>();
foreach(var rowItem in dicts[colItem.Key])
{
rowItem.Value.Sort();
colList.AddRange(rowItem.Value);
}
result.Add(colList);
}
return result;
}
public void DFSHelper(TreeNode root, int rowNum, int colNum)
{
if (root == null)
return;
if (!dicts.ContainsKey(colNum))
dicts.Add(colNum, new SortedDictionary<int, List<int>>());
if (!dicts[colNum].ContainsKey(rowNum))
dicts[colNum].Add(rowNum, new List<int>());
dicts[colNum][rowNum].Add(root.val);
DFSHelper(root.left, rowNum + 1, colNum - 1);
DFSHelper(root.right, rowNum + 1, colNum + 1);
}
}
# 记录每一个列出现的所有数字(带行数),按列排序,按行排序,按值排序
class Solution:
def verticalTraversal(self, root: TreeNode) -> List[List[int]]:
hashmap = defaultdict(list)
def dfs(node, x, y):
if not node:
return
hashmap[y].append((x,node.val))
dfs(node.left, x+1, y-1)
dfs(node.right,x+1, y+1)
dfs(root, 0, 0)
# print(hashmap)
return [list(zip(*sorted(hashmap[i])))[1] for i in sorted(hashmap.keys())]
class Solution {
private:
vector<vector<int>> nodes;
void dfs(TreeNode* root, int row, int col){
if (root == nullptr) return;
vector<int> tmp = {col, row, root->val};
nodes.push_back(tmp);
dfs(root->left, row+1, col-1);
dfs(root->right, row+1, col+1);
}
public:
vector<vector<int>> verticalTraversal(TreeNode* root) {
vector<vector<int>> ans;
dfs(root, 0, 0);
sort(nodes.begin(), nodes.end());
int lastCol = INT_MIN;
for(auto&ele:nodes){
int col = ele[0];
int row = ele[1];
int value = ele[2];
if (col != lastCol){
lastCol = col;
vector<int> tmp;
ans.push_back(tmp);
}
ans.back().push_back(value);
}
return ans;
}
};
++
给你二叉树的根结点 root
,请你设计算法计算二叉树的 垂序遍历 序列。
对位于 (row, col)
的每个结点而言,其左右子结点分别位于 (row + 1, col - 1)
和 (row + 1, col + 1)
。树的根结点位于 (0, 0)
。
二叉树的 垂序遍历 从最左边的列开始直到最右边的列结束,按列索引每一列上的所有结点,形成一个按出现位置从上到下排序的有序列表。如果同行同列上有多个结点,则按结点的值从小到大进行排序。
返回二叉树的 垂序遍历 序列。
class Solution:
def verticalTraversal(self, root: TreeNode) -> List[List[int]]:
nodes = []
def dfs(root, col, row):
if not root:
return
nodes.append((col, row, root.val))
dfs(root.left, col - 1, row + 1)
dfs(root.right, col + 1, row + 1)
dfs(root, 0, 0)
nodes.sort() # 按照col为第一关键字升序,row为第二关键字升序,val为第三关键字升序
last_col = float('-inf')
res = []
for col, row, val in nodes:
if col != last_col:
res.append([])
last_col = col
res[-1].append(val)
return res
class Solution {
public:
vector<vector<int>> verticalTraversal(TreeNode* root) {
vector<tuple<int, int, int>> nodes;
// function写法?
function<void(TreeNode*, int, int)> dfs = [&](TreeNode* root, int col, int row){
if(!root){
return;
}
nodes.emplace_back(col, row, root->val);
dfs(root->left, col - 1, row + 1);
dfs(root->right, col + 1, row + 1);
};
dfs(root, 0, 0);
sort(nodes.begin(), nodes.end());
vector<vector<int>> res;
int last_col = INT_MIN;
for(const auto& [col, row, val]: nodes){
if(col != last_col){
last_col = col;
res.emplace_back();
}
res.back().emplace_back(val);
}
return res;
}
};
垂直适合深度遍历,每一个记载一个 然后进行排序
HashMap<Integer, HashMap<Integer, List<Integer>>> integerListHashMap = new HashMap<>();
public List<List<Integer>> verticalTraversal(TreeNode root) {
if(root==null){
return null ;
}
dfs(0,0,root);
List<List<Integer>> res = new ArrayList<>();
Set<Integer> integers = integerListHashMap.keySet();
List<Integer> result = new ArrayList<>(integers);
List<Integer> temp = new ArrayList<>(integers);
Collections.sort(result);
for (Integer num:result) {
temp=new ArrayList<>();
HashMap<Integer, List<Integer>> midVale = integerListHashMap.get(num);
List<Integer> midValeList= new ArrayList<>(midVale.keySet());
Collections.sort(midValeList);
for(Integer midValue:midValeList){
List<Integer> integers1 = midVale.get(midValue);
Collections.sort(integers1);
temp.addAll(integers1);
}
res.add(temp);
}
return res;
}
public void dfs(Integer x,Integer y,TreeNode treeNode){
if(integerListHashMap.containsKey(y)){
if(integerListHashMap.get(y).containsKey(x)){
integerListHashMap.get(y).get(x).add(treeNode.val);
Collections.sort(integerListHashMap.get(y).get(x));
}else {
List<Integer> value=new ArrayList<Integer>();
value.add(treeNode.val);
integerListHashMap.get(y).put(x,value);
}
}else {
HashMap<Integer, List<Integer>> midVale = new HashMap<>();
List<Integer> value=new ArrayList<Integer>();
value.add(treeNode.val);
midVale.put(x,value);
integerListHashMap.put(y,midVale);
}
if(treeNode.left!=null){
dfs(x+1,y-1,treeNode.left);
}
if(treeNode.right!=null){
dfs(x+1,y+1,treeNode.right);
}
}
复杂度分析 ·时间复杂度;O(nlogN) -空间复杂度:O(n)
又是看不懂题目的一天
class Solution {
Map<TreeNode, int[]> map = new HashMap<>(); // col, row, val
public List<List<Integer>> verticalTraversal(TreeNode root) {
map.put(root, new int[]{0, 0, root.val});
dfs(root);
List<int[]> list = new ArrayList<>(map.values());
Collections.sort(list, (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];
});
int n = list.size();
List<List<Integer>> ans = new ArrayList<>();
for (int i = 0; i < n; ) {
int j = i;
List<Integer> tmp = new ArrayList<>();
while (j < n && list.get(j)[0] == list.get(i)[0]) tmp.add(list.get(j++)[2]);
ans.add(tmp);
i = j;
}
return ans;
}
void dfs(TreeNode root) {
if (root == null) return ;
int[] info = map.get(root);
int col = info[0], row = info[1], val = info[2];
if (root.left != null) {
map.put(root.left, new int[]{col - 1, row + 1, root.left.val});
dfs(root.left);
}
if (root.right != null) {
map.put(root.right, new int[]{col + 1, row + 1, root.right.val});
dfs(root.right);
}
}
}
var verticalTraversal = function(root) { const nodes = []; dfs(root, 0, 0, nodes); nodes.sort((tuple1, tuple2) => { if (tuple1[0] !== tuple2[0]) { return tuple1[0] - tuple2[0]; } else if (tuple1[1] !== tuple2[1]) { return tuple1[1] - tuple2[1]; } else { return tuple1[2] - tuple2[2]; } });
const ans = [];
let lastcol = -Number.MAX_VALUE;
for (const tuple of nodes) {
let col = tuple[0], row = tuple[1], value = tuple[2];
if (col !== lastcol) {
lastcol = col;
ans.push([]);
}
ans[ans.length - 1].push(value);
}
return ans;
}
const dfs = (node, row, col, nodes) => { if (node === null) { return; } nodes.push([col, row, node.val]); dfs(node.left, row + 1, col - 1, nodes); dfs(node.right, row + 1, col + 1, nodes); }
class Solution {
Map<Integer, List<Integer[]>> vertMap = new TreeMap<>();
public List<List<Integer>> verticalTraversal(TreeNode root) {
List<List<Integer>> res = new ArrayList<>();
preOrder(root, 0, 0);
for (List<Integer[]> list : vertMap.values()) {
list.sort((a1, a2) -> (a1[0] == a2[0]) ? (a1[1] - a2[1]) : (a1[0] - a2[0]));
List<Integer> temp = new ArrayList<>();
for (Integer[] nums : list) {
temp.add(nums[1]);
}
res.add(temp);
}
return res;
}
private void preOrder(TreeNode root, int x, int y) {
if (root == null) {
return;
}
List<Integer[]> list = vertMap.getOrDefault(y, new ArrayList<>());
list.add(new Integer[]{x, root.val});
vertMap.put(y, list);
preOrder(root.left, x + 1, y - 1);
preOrder(root.right, x + 1, y + 1);
}
}
思路 dfs 按顺序找出节点位置 sort排序,根据相同col 合并
代码
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
复杂度 时间 O(nlogn) 空间 O(n)
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 之间。