1、题目描述
给你一个单链表的头节点 head
,请你判断该链表是否为回文链表。如果是,返回 true
;否则,返回 false
。
示例 1:
输入:head = [1,2,2,1] 输出:true
2、初始思路
2.1 思路
通过将前段和后段的数据都存在列表中,然后比较列表中的数值,从而判断是否是回文数列。
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def isPalindrome(self, head: Optional[ListNode]) -> bool:
pa = head
pb = head
n = 0
#print(head.val)
while pa:
n += 1
pa = pa.next
m = n // 2
if n == 1:
return True
list1 = []
list2 = []
a = 0
while a < m:
list1.append(pb.val)
pb = pb.next
a += 1
b = 0
if n%2 != 0:
pb = pb.next
while b < m:
list2.append(pb.val)
pb = pb.next
b += 1
list2 = list2[::-1]
print("list1:",list1)
print("list2:",list2)
if list1 == list2:
return True
else:
return False
2.2 缺点
运行时间长,运行空间占用为O(N).
3 优化算法
3.1 思路1
使用slow和fast两个指针,这样可以找到链表的中点,从而反转后半部分的链表,并于前一部分的链表进行比较,判断是否是回文链表。
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def isPalindrome(self, head: Optional[ListNode]) -> bool:
slow, fast = head, head
if head.next == None:
return True
while fast and fast.next:
slow = slow.next
fast = fast.next.next
pre = None
current = slow
while current:
snext = current.next
current.next = pre
pre = current
current = snext
one = head
two = pre
while two:
if two.val != one.val:
return False
two = two.next
one = one.next
return True
3.2 思路2
使用一个列表保存链表的值,若为回文序列,则正反列表的值都应当一致。
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def isPalindrome(self, head: Optional[ListNode]) -> bool:
if not head or not head.next:
return True
listnode = []
while head:
listnode.append(head.val)
head = head.next
return listnode == listnode[::-1]
4 总结--(while head: )和 (while head and head.next:)的区别
1. while head:
作用: 遍历整个链表,直到链表的末尾(即 head 为 None)。适用于需要访问链表中所有节点的情况。
停止条件: 当 head 为 None 时,循环停止。
适用场景: 需要遍历整个链表的所有节点。 例如:计算链表长度、将链表转换为列表、打印链表等。
2. while head and head.next:
作用: 遍历链表,但只遍历到倒数第二个节点(即 head.next 为 None 时停止)。适用于只需要访问链表的前半部分或需要提前停止的情况。
停止条件: 当 fast 为 None 或 fast.next 为 None 时,循环停止。
适用场景: 需要提前停止遍历链表,例如: 找到链表的中间节点(快慢指针)。 判断链表是否有环(快慢指针)。 只遍历链表的前半部分。