2026/1/14 6:17:51
网站建设
项目流程
绍兴网站公司网站制作,深圳沙头网站建设,微信5000人接推广费用,春播网站是谁做的【LeetCode 958】判定完全二叉树#xff1a;警惕 BFS 中的“管中窥豹”陷阱
在二叉树的面试题中#xff0c;判定完全二叉树#xff08;Check Completeness of a Binary Tree#xff09;是一道考察层序遍历#xff08;BFS#xff09;细节处理的经典题目。
很多同学知道这道…【LeetCode 958】判定完全二叉树警惕 BFS 中的“管中窥豹”陷阱在二叉树的面试题中判定完全二叉树Check Completeness of a Binary Tree是一道考察层序遍历BFS细节处理的经典题目。很多同学知道这道题要用队列Queue做 BFS但在处理“何时结束”、“如何判定失败”的逻辑上很容易掉进思维陷阱。今天我们就通过两段代码的对比一段 100% 通过一段 95% 通过来揭示算法设计中的局部视野 vs 全局视野的差异。1. 题目核心难点完全二叉树的定义通俗来说就是前面的层必须是满的。最后一层的节点必须紧凑地靠左排列。中间不能有空洞。这意味着如果我们对树进行层序遍历BFS将所有节点包括空节点null按顺序放入队列。那么一旦出现了第一个null后面就绝对不能再出现任何非null的节点。如果出现了说明树中间断开了不是完全二叉树。2. 案例分析为什么代码 2 只能通过 95%让我们先来看看这段“差一点就对了”的代码Code 2。它的思路看起来很机智在遍历过程中盯着当前节点和下一个节点看。❌ Code 2存在逻辑漏洞classSolution{publicbooleanisCompleteTree(TreeNoderoot){QueueTreeNodequeuenewLinkedList();queue.offer(root);while(!queue.isEmpty()){TreeNodecurqueue.poll();// 试图通过“当前节点”和“下一个节点(peek)”的关系直接下定论if(curnullqueue.peek()!null)returnfalse;// 漏洞 1if(curnullqueue.peek()null)returntrue;// 漏洞 2 (致命)// 注意这里其实还会抛出空指针异常因为当 cur 为 null 时// 下面的代码会尝试 cur.left虽然题目可能保证了数据但在逻辑上是不严谨的。// 假设我们忽略空指针问题只看逻辑if(cur!null){queue.offer(cur.left);queue.offer(cur.right);}}returntrue;}}致命死穴管中窥豹局部视野这段代码最大的问题在于这句话if(cur null queue.peek() null) return true;它的逻辑是如果我是空的而且我后面排队的那个人也是空的那肯定结束了返回true。反例打击假设树的层序结构是[Node, null, null, Node]。这显然不是完全二叉树中间缺了两个。当代码执行到第一个null时cur是null。queue.peek()是第二个null。代码直接判定return true。只要连着出现两个空节点代码 2 就会误判为“通过”完全忽略了队列后面可能还藏着一个非空的节点queue.peek()只能看一眼下一个看不到队尾这就是典型的“局部视野”导致的错误。3. 优秀解法全局扫视Code 1来看看那段完美通过的代码Code 1。它的思路非常稳健分为两个阶段。✅ Code 1标准答案classSolution{publicbooleanisCompleteTree(TreeNoderoot){QueueTreeNodequeuenewLinkedList();queue.offer(root);// 阶段一无脑入队直到遇到第一个 nullwhile(!queue.isEmpty()){TreeNodecurqueue.poll();if(cur!null){// 关键点不管孩子是不是 null都放进去// 这保证了队列里完整保留了树的结构包括空位queue.offer(cur.left);queue.offer(cur.right);}else{// 遇到了第一个空节点阶段一结束break;}}// 阶段二排查剩余队列// 既然已经遇到了空节点那么如果这棵树是完全的// 队列里剩下的所有东西必须全都是 null。// 只要发现任何一个活着的节点直接判死刑。while(!queue.isEmpty()){if(queue.peek()!null){returnfalse;}queue.poll();}returntrue;}}为什么 Code 1 更优逻辑分层清晰前半场正常遍历一旦遇到空节点立刻停止“生成新节点”的操作。后半场专门负责“验尸”。检查剩下的队列是否纯净全空。全局视野它没有在遇到null时急着下结论而是用第二个while循环把队列彻底检查一遍。这就避免了“连续两个 null 后面藏着一个 Node”的坑。数据结构的正确使用它利用了队列 FIFO 的特性把二叉树拉成了一维的线性结构。判定完全二叉树本质上就是看这个线性结构中所有的null是否都集中在最后面。[Node, Node, Node, null, null]- ✅ 是[Node, null, Node, null]- ❌ 否[Node, null, null, Node]- ❌ 否Code 2 会挂在这里4. 总结在解决 BFS 相关题目时我们要格外注意状态的连续性。Code 2 的失败在于试图用O(1)O(1)O(1)的视野peek去推断O(N)O(N)O(N)的结局犯了“急于求成”的错误。Code 1 的成功在于它捕捉到了完全二叉树的本质特征“遇到空节点后后续必须全为空”并用两个循环严谨地实现了这个逻辑。写算法题时不要只盯着眼前的peek()要想到队列深处可能还藏着“魔鬼”。