【发布时间】:2022-01-07 00:59:39
【问题描述】:
我正在分析我写给 Leetcode 问题的解决方案的时间复杂度,Vertical Order Traversal of a Binary Tree
该问题提供了一个二叉树,并要求返回一个列表列表,其中每个列表对应于树中的垂直列,并且每个列表从上到下排序,同一行和列中的值按数字排序.
我的代码如下所示,但总结一下,我使用两个队列逐级执行广度优先搜索。我同样使用两张地图。一个映射保存整个表的列和该列中的值之间的关系,而其他映射用于类似的目的,但它一次只保存一个级别的值。这使我们能够对每个级别内的潜在联系进行排序,然后将其值添加到上述地图中。在程序结束时,包含所有级别信息的地图被转换为 Leetcode 评分器的列表列表。
我无法分析排序逻辑的时间复杂度。最坏的情况是在完全二叉树中排序最多的情况。到目前为止,这是我一直在想的:
对于这个完整的二叉树,节点已经用它们各自的列进行了标记,在顶部,我显示了每一列在每个级别的频率。我在图像上有这些数据,因为 Stack Overflow 在提交这篇文章后没有正确呈现表格。
列值的大小并不是特别重要,但出现的频率模式是帕斯卡三角/二项式系数展开的模式。事后看来,从右/左子节点的父节点列中添加/减去 1 是有道理的。列号的频率表示必须排序的该级别的列表大小(瓶颈)。
鉴于此,我可以重复
递归中的L指的是二叉树中的层级。每个级别的总工作量是之前级别完成的工作量,加上在该级别对具有可变大小的列表进行排序的工作(大小相对于二项式展开系数是可变的)。从这里开始,我不知道该去哪里。 L,或 logN,表示树中的 N 个元素。
直觉让我相信这种重复会产生以下表达式
但这仍然不是很清楚,我也不确定它是否正确(就像我说的,直觉---不是证明---导致我这样做)。这看起来对吗?有没有办法简化我还没有看到的?
我在下面附上了实现此功能的 Java 代码。谢谢,如果您有任何问题,请告诉我。
* 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 {
/*
* Map<TreeNode, Integer> to keep track of column for each treenode
* Map<Integer, List<Integer>> to keep track of columns and the values in the column
* Map<Integer, List<Integer>> to keep track of columns and the values in the column
FOR EACH ROW
* Breadth first search
* - as adding to queue, add to column map
* - use a 2 queue approach for each level in breadth first search
* - when each level of BFS is finished, sort third map, then add all to second map
and clear it
*/
public List<List<Integer>> verticalTraversal(TreeNode root) {
Map<TreeNode, Integer> columns = new HashMap<>();
final Map<Integer, List<Integer>> table = new HashMap<>();
Map<Integer, List<Integer>> levelTable;
Queue<TreeNode> bfsQueue;
Queue<TreeNode> nextLevel = new ArrayDeque<>();
int minColOverall = Integer.MAX_VALUE;
nextLevel.offer(root);
columns.put(root, 0);
while(!nextLevel.isEmpty()){
bfsQueue = nextLevel;
nextLevel = new ArrayDeque<>();
levelTable = new HashMap<>();
int minCol = Integer.MAX_VALUE;
while(!bfsQueue.isEmpty()){ // Evaluate each level individually
TreeNode node = bfsQueue.poll();
int column = columns.remove(node);
minCol = Math.min(minCol,column);
if(!levelTable.containsKey(column))
levelTable.put(column, new ArrayList<Integer>());
levelTable.get(column).add(node.val);
if(node.left != null){
nextLevel.offer(node.left);
columns.put(node.left, column-1);
}
if(node.right != null){
nextLevel.offer(node.right);
columns.put(node.right, column+1);
}
}
minColOverall = Math.min(minCol, minColOverall);
for(int m = minCol; !levelTable.isEmpty(); m+=2){ // After level, add sorted col vals to final table
if(!levelTable.containsKey(m))
continue;
List<Integer> level = levelTable.remove(m);
Collections.sort(level);
if(!table.containsKey(m))
table.put(m, new ArrayList<Integer>());
table.get(m).addAll(level);
}
}
// Transform map to list
final List<List<Integer>> answer = new ArrayList<>();
while(!table.isEmpty())
answer.add(table.remove(minColOverall++));
return answer;
}
}```
【问题讨论】:
-
正如你所说,紧束缚将是一个混乱的总结。我不会尝试解决它,尽管看起来你在正确的轨道上。好消息是您可以确定 O(n log n) 是正确的。很难想象一个实际案例中,这与紧密界限之间的差异将是有意义的。 O(n log n) 甚至可能紧。
标签: algorithm sorting time-complexity big-o