在算法面试中,链表作为数据结构的基础之一,经常成为考察的重点。其中,反转单链表和判断链表是否有环是两个非常典型的题目,它们不仅考验了面试者对链表操作的基本功,还涉及到递归、迭代、快慢指针等多种算法思想的运用。本章节将详细探讨这两个问题的解法,并通过代码示例帮助读者深入理解。
给定一个单链表的头节点 head
,要求原地反转链表中的所有节点,并返回反转后的链表头节点。
next
指针指向其前一个节点,直至遍历完成。迭代过程中需要保存当前节点的下一个节点,以防链表断开。next
指针,实现反转。
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
def reverseListIteratively(head):
prev = None
current = head
while current:
next_temp = current.next # 保存当前节点的下一个节点
current.next = prev # 反转当前节点的next指针
prev = current # 移动prev和current
current = next_temp
return prev # 当遍历完成时,prev即为新的头节点
# 示例
head = ListNode(1, ListNode(2, ListNode(3, ListNode(4, ListNode(5)))))
reversed_head = reverseListIteratively(head)
# 验证反转结果
while reversed_head:
print(reversed_head.val, end=" ")
reversed_head = reversed_head.next
# 输出: 5 4 3 2 1
def reverseListRecursively(head):
if not head or not head.next:
return head
new_head = reverseListRecursively(head.next)
head.next.next = head # 反转当前节点与下一个节点的连接
head.next = None # 将当前节点的next指针置为None,防止成环
return new_head
# 示例同上,使用递归函数
reversed_head_recursive = reverseListRecursively(head)
# 验证反转结果(同上)
给定一个单链表的头节点 head
,要求判断链表中是否存在环。
def hasCycle(head):
if not head or not head.next:
return False
slow = head
fast = head.next
while slow != fast:
if not fast or not fast.next:
return False
slow = slow.next
fast = fast.next.next
return True
# 示例
# 假设存在一个有环的链表
# head -> 1 -> 2 -> 3 -> 4 -> 5 -> 3 (环开始于节点3)
# 判断环的存在
has_cycle = hasCycle(head_with_cycle) # 假设head_with_cycle为上述有环链表的头节点
print(has_cycle) # 输出: True
本章节详细讲解了反转单链表和判断链表是否有环两个问题的解题思路与实现方法。反转单链表通过迭代和递归两种方式实现,各有优劣,迭代法空间复杂度低但代码相对冗长,递归法代码简洁但可能面临栈溢出的风险。判断链表是否有环则主要介绍了快慢指针法,该方法以其高效的空间利用率和清晰的逻辑成为解决此类问题的首选。通过这两个问题的探讨,读者不仅能加深对链表操作的理解,还能掌握递归、迭代、快慢指针等算法思想的应用。