234. 回文链表
原始题目链接:https://leetcode-cn.com/problems/palindrome-linked-list/
解题思路:
这道题如果使用额外的空间是比较容易解题的,把链表的值都存放到一个数组里,遍历数组的元素看是否满足条件,这个时候空间复杂度是O(n),所以不是最优解。如果想使用O(1)的空间复杂度,就要使用指针进行原地操作。具体分为5个步骤:
- 查找链表的中间节点,将链表分为两部分
- 反转链表的后半部分
- 遍历前后两部分链表的值是否一样,一样就是回文链表返回True,否则返回False
- 还原反转的链表,保持与原链表一致
- 返回结果,True 或者 False
具体实现看代码及注释。
代码实现:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
# 查找链表中间节点的函数,返回中间节点
def find_mid_node(self, head: ListNode) -> ListNode:
# 使用快慢指针查找
fast, slow = head, head
while fast.next and fast.next.next:
fast = fast.next.next
slow = slow.next
return slow
# 反转链表,参数是要反转链表的头结点
# 返回值是反转后链表的头结点
def reverse_listnode(self, head: ListNode) -> ListNode:
pre_node = None
cur_node = head
while cur_node:
cur_next_node = cur_node.next
cur_node.next = pre_node
pre_node = cur_node
cur_node = cur_next_node
return pre_node
def isPalindrome(self, head: ListNode) -> bool:
if head is None:
return True
# 判断回文链表:
# 【1】查找链表的中间节点,将链表分为两部分
# 【2】反转链表的后半部分
# 【3】遍历前后两部分链表的值是否一样,一样就是回文链表返回True,否则返回False
# 【4】还原反转的链表,保持与原链表一致
# 【5】返回结果,True 或者 False
mid_node = self.find_mid_node(head)
right_part_head = mid_node.next
right_part_reverse_head = self.reverse_listnode(right_part_head)
left_part_head = head
while right_part_reverse_head:
if right_part_reverse_head.val != left_part_head.val:
return False
right_part_reverse_head = right_part_reverse_head.next
left_part_head = left_part_head.next
self.reverse_listnode(right_part_reverse_head)
return True
参考文献:
https://leetcode-cn.com/problems/palindrome-linked-list/solution/hui-wen-lian-biao-by-leetcode-solution/