一.问题描述
Given a singly linked list, determine if it is a palindrome.
Example 1:
Input: 1->2 Output: false
Example 2:
Input: 1->2->2->1 Output: true
Follow up:
Could you do it in O(n) time and O(1) space?
二.解题思路
难点主要在要求常数内存。
首先若不要求常数内存,则:
首先遍历链表,将链表每一个数加进数组。
然后遍历数组,判断数组nums[i]==nums[-i-1],若有一个不相等则说明不是回文链表。
时间复杂度O(N),空间复杂度O(N)
常数内存:
如果是回文链表,说明可以把链表切两半,然后这两半是对称的(如果是奇数,不考虑最中间那个数,因为是共有的,不用进行处理)。
扫描二维码关注公众号,回复:
8837396 查看本文章
那么我们可以遍历到链表的一半,然后从这前一办部分开始将链表反转,然后再遍历这两个半链表,判断每个元素是否相等。
问题就是如何找到链表的一半,毕竟我们不知道链表的长度。
方法就是用两个指针,一个指针每次跑一格,一个指针每次跑两格,当每次跑两格的指针跑到头的时候,那每次跑一个的指针就跑到整个链表的一半的地方,然后从这里开始翻转链表。
唯一要注意一下的地方就是链表长度是奇数还是偶数,如果是奇数的话,跳过最中间那个数,因为那个数没有意义,具体看代码吧。
时间复杂度:O(N),空间复杂度O(1)
更多leetcode算法题解法: 专栏 leetcode算法从零到结束 或者 leetcode 解题目录 Python3 一步一步持续更新~
三.源码
1.非常数内存
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def isPalindrome(self, head: ListNode) -> bool:
nums,res=[],True
while head:
nums.append(head.val)
head=head.next
for i in range(len(nums)//2):
if nums[i]!=nums[-i-1]:return False
return res
2.常数内存
class Solution:
def isPalindrome(self, head: ListNode) -> bool:
def reverseLinkedList(head):
p,rvs_head,head=None,head,head.next
while head:
rvs_head.next=p
p=rvs_head
rvs_head=head
head=head.next
rvs_head.next=p
return rvs_head
if not head or not head.next:return True
slow,fast,res=head,head.next,True
isOdd=False
while fast:
if not fast.next:break
if not fast.next.next:
isOdd=True
break
slow,fast=slow.next,fast.next.next
new_head=slow.next.next if isOdd else slow.next
slow.next=None
rvs_head=reverseLinkedList(new_head)
while head:
if head.val!=rvs_head.val:return False
head,rvs_head=head.next,rvs_head.next
return res