Leetcode 每日一题
题目链接: 234. 回文链表
解题思路: 使用异或的性质,对于一个数a, 对他自己进行异或,值为0。不难得出:a ^ x ^ a = x 。有了上述的定理,我们可以将整个给定的链表节点值加上位置信息(可以自己设计Hash, 本文直接采用与中间位置的距离与链表节点的值的和)中的值进行异或,若最后的值等于0或者中间的值,那么他一定是回文串。
定义哈希函数为: Hash(node) = node.val + (position - len_list/2)
比如(support为辅助变量,进行异或计算)对于回文串: [1,5,3,5,1]
对于每一个节点:
H(0) = 3, support = 3
H(1) = 6,support = 3^6 = 5
H(2) = 3,support = 3^6^3 = 6
H(3) = 6,support = 3^6^3^6 = 0
H(4) = 3,support = 3^6^3^6^3 = 3
根据上述的例子很容易得出结论。
时间复杂度为O(n) 常数项有点高,因为需要额外计算一次链表长度;空间复杂度为O(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:
list_len = -1
node = head
# 计算链表长度
while node != None:
list_len += 1
node = node.next
# 长度为1 或 0
if list_len == 0 or list_len == -1:
return True
node = head
# support 为辅助计算异或的变量,index为位置信息,mid_val 表示链表长度为奇数时的中间值。
support, index, mid_val = 0, 0, 0
while node != None:
val = int(abs(index - (list_len/2))) + node.val
# 异或叠加
support ^= val
if index == int(list_len/2):
mid_val = node.val
# print(val, support)
node = node.next
index += 1
# 偶数个数
if (list_len + 1) % 2 == 0 and support == 0:
return True
# 奇数个数
if (list_len + 1) % 2 == 1 and support == mid_val:
return True
return False