调换链表回文判断代码中AND操作数顺序为何在输入[1,0,1]时出错?
为什么调换与运算操作数顺序会导致回文链表判断出错?
嘿,这个问题其实是踩了递归执行顺序和非短路与运算的双重坑,咱们一步步拆解来看:
先搞懂原代码的正确逻辑
原代码里的check函数是靠递归的栈特性实现“从后往前遍历链表”的,配合全局的temp指针从前往后移动,刚好实现首尾节点的一一对应比较:
bool check(ListNode* p) { if (NULL == p) return true; // 先递归到链表最末尾,再回溯做比较 bool isPal = check(p->next) & (temp->val == p->val); temp = temp->next; // 比较完才移动temp,保证下一次回溯对应下一个节点 return isPal; }
拿输入[1,0,1]来说,执行流程是这样的:
- 递归一路深入,直到
p为null,此时递归栈里依次压着1→0→1三个节点。 - 从栈顶开始回溯:
- 先处理最末尾的
1:此时temp指向头节点1,比较相等,temp后移到0,返回true。 - 再处理中间的
0:此时temp指向0,比较相等,temp后移到1,返回true。 - 最后处理第一个
1:此时temp指向末尾的1,比较相等,返回true。
整个过程完美实现了首尾对应比较。
- 先处理最末尾的
调换顺序后哪里出问题了?
当把代码改成bool isPal = (temp->val == p->val) & check(p->next);后,因为&是非短路与运算——不管左边结果是什么,右边的表达式一定会执行,而且执行顺序是先左后右。这直接打乱了原有的逻辑:
同样拿[1,0,1]走一遍流程:
- 第一次调用
check(1):先执行temp->val == p->val(此时temp是头节点1,p也是1,结果为true),然后才调用check(0)。 - 调用
check(0):先执行temp->val == p->val(此时temp还是头节点1,p是0,结果为false),然后调用check(1)。 - 调用
check(1):先执行temp->val == p->val(temp依旧是1,p是1,结果为true),然后调用check(null)返回true。 - 回溯到
check(1):isPal = true & true为true,temp后移到0,返回true。 - 回溯到
check(0):isPal = false & true为false,temp后移到1,返回false。 - 回溯到最开始的
check(1):isPal = true & false为false,最终返回false——明显错误!
问题的核心在于:比较操作的执行时机完全错了。原代码是在递归回溯时(从后往前)才做比较,此时temp刚好走到对应位置;而调换顺序后,比较操作提前到了递归深入前(从前往后),temp还没走到对应节点就提前比较,自然会出现不匹配的情况。
额外补充:如果用&&会怎样?
如果这里用的是短路与运算符&&,调换顺序后问题会更严重:一旦左边比较为false,右边的递归直接不会执行,链表后面的节点根本没机会被处理,直接返回false,错误范围更大。而&因为会执行两边,只是时机错了,所以还能走完递归流程,但结果依旧错误。
总结一下:
- 原代码利用递归栈的回溯特性,配合
temp的延后移动,实现了首尾节点的精准对应。 - 调换
&两边的顺序后,比较操作提前执行,破坏了temp和回溯节点的对应关系,导致判断出错。
内容的提问来源于stack exchange,提问作者Justin Drake
相关产品推荐
相关产品推荐

