python - 使用递归检查回文时,反向指针如何移动?
问题描述
我找到了一个递归解决方案来检查链表是否是回文:
def isPalindrome(self, head: ListNode) -> bool:
self.front_pointer = head
def recursively_check(head):
if head:
if not recursively_check(head.next):
return False
if self.front_pointer.val != head.val:
return False
self.front_pointer = self.front_pointer.next
return True
return recursively_check(head)
声明后'if head'
:
当“recursively_check(head.next)”指向 None 时,为什么我们在第一个 if 语句中返回 False?这样就好了,不是吗?因为它只是意味着我们已经到达链表的末尾,还是我读错了?
对于第二个 if 语句,这种说法是有道理的——在我看来,这是检查第一个节点front_pointer
和最后一个节点head
是否相同?
那么我们只是简单地将最初指向链表头部的front_pointer移动到下一个要检查的节点?但是,虽然我理解这一点,但从后端,我们如何从最后一个节点移动到倒数第二个节点?
最后,为什么我们要返回递归调用recursively_check()
?我不知道我们什么时候会到达这个代码——因为我们到达这里时会返回 True 或 False,不是吗?
解决方案
语句之后
if head
:为什么我们要返回False
第一个 if 语句,什么时候recursively_check(head.next)
指向None
?这样就好了,不是吗?因为它只是意味着我们已经到达链表的末尾,还是我读错了?
recursively_check(head.next)
不“指向None
”。它是一个布尔值:要么是True
,要么是False
。将 a 解释True
为“到目前为止它看起来像回文”,并将 a 解释False
为“这绝对不是回文”。
这个特别的目的是为了在递归调用树中检测到更深return False
的故障时退出递归。在这里,我们只是将该消息传递给调用者,调用者也会这样做。它与到达列表末尾无关。它是由递归树中更深层次的差异触发的。
对于第二个 if 语句,这种说法是有道理的——在我看来,它是在检查第一个节点 front_pointer 和最后一个节点 head 是否相同?
是的,第一次执行时,就是这样。
那么我们只是简单地将
front_pointer
最初指向链表头部的 , 移动到下一个要检查的节点?
是的
但是,虽然我理解这一点,但从后端,我们如何从最后一个节点移动到倒数第二个节点?
这由递归处理。每个递归调用都得到自己的head
变量。当我们用 初始化它时head.next
,更深层次的递归调用将在列表中进一步head
初始化。
这意味着当我们回溯到某个递归级别时,我们会进入一个执行上下文,该上下文的head
变量设置为前一个节点,而不是更深层调用正在使用的节点(正如我们给它的那样head.next
)。因此,仅通过退出当前执行上下文,我们就回退到先前的值head
,这对应于在列表中后退一步。但是请注意,我们head
这里的变量与列表中的节点一样多。它们都在递归调用堆栈中堆叠在一起。通过展开调用堆栈,我们可以使用前一个head
变量。
最后,为什么我们要返回递归调用
recursively_check()
?我不知道我们什么时候会到达这个代码——因为当我们到达这里时,我们会返回 True 或 False,不是吗?
我们立即达成此声明。当我们到达那里时,它上面的函数还没有执行。正是这条语句将启动递归,我们需要从该调用中获取信息,而该信息就是我们想要返回的信息。
这是 的唯一return
声明isPalindrome
。其他return
语句recursively_check
仅服务。他们不执行退货isPalindrome
。
每次我们退出嵌套执行时,recursively_check
我们都会多测试一对节点。如果我们发现价值差异,我们开始返回False
。如上所述,False
从那时起,这将成为所有未完成调用的返回值recursively_check
,包括直接在 中进行的调用isPalindrome
。
另一方面,只要比较相等,每个嵌套调用True
都会返回a。recursively_check
如果事实证明比较总是相等的,那么isPalindrome
's 的调用recursively_check
也会得到True
回报。
推荐阅读
- docker - 让 docker build --memory-swap=20g 使用可用的交换空间?
- r - 使用 scatter3D() (package plot3D) 在 R 中绘制多元线性回归
- javascript - 行为不同的外部 JS 文件
- c# - C# SaveFileDialog 使用从 API 中提取的 JSON 数据
- reactjs - SpringBoot with React - Rest API 在刷新时与 React Routes 发生冲突
- regex - 正则表达式:用 SublimeText 3 中的文件完整路径的一部分替换文本
- typescript - TS 如何解释具有相同命名函数属性但不同签名的类型的交集(与接口相同生成错误)?
- java - Java - 将实例变量传递给 this() 方法
- flutter - 在 Dart-Web 应用程序中引用本地路径包
- vue.js - Vuelidate 简单的必需验证