234. Palindrome Linked List

Overview
Check whether the value in the linked list is a palindrome or not.
Solution 1: List
Algorithm
-
Create a
numslist to save thenode.valin linked list nodes. -
Iterate through the linked list and append the
node.valto thenumslist. -
Initialize
leftandrighttwo pointers to point to the list head and tail. -
Iterate through the
numslist.
If the number at the left index is not equal to the number at right index,
it means it's not a palindrome linked list. Return false immediately. -
Return true because the left-hand side is equal to the reversed right-hand side.
Implement
class Solution: def isPalindrome(self, head: Optional[ListNode]) -> bool: nums: list[int] = [] while head is not None: nums.append(head.val) head = head.next left = 0 right = len(nums) - 1 while left < right: if nums[left] != nums[right]: return False left += 1 right -= 1 return True
Complexity Analysis
Time complexity: O(n)
Iterate though the linked list to save the node.val into nums takes O(n).
Iterate through the nums list will take half of the nums list
if the numbers are all unique in half of the nums, takes O(n/2).
The total time complexity can be simplified to O(n).
Space complexity: O(n)
We use an additional list to save the node.val in the linked list, taking O(n) space.
Solution 2: Two Pointer
Algorithm
-
Initialize
slowandfastpointers and point on thehead. Initializepreviousas None. -
This iteration combines two techniques.
First, we use slow and fast pointer:
slow advances by one step, and fast advances by two steps.
When fast reaches the end, slow points to the middle node of the linked list.Another technique involves reversing the left half of the linked list,
using the algorithm discussed in question 206 yesterday.
previouswill point to the end of the left half and the left hand side had been reversed.
slowwill point on the start of the right half. -
If the length of the linked list is odd, we need to move slow one more time
so it points to the correct middle position. -
Iterate through
previousandslowto check if thenode.valis equals or not.
Return false immediately if thenode.valis not equal. -
Return true because the values of the previous nodes are equal to the values of the slow nodes.
Implement
class Solution: def isPalindrome(self, head: Optional[ListNode]) -> bool: slow = fast = head previous: Optional[ListNode] = None while fast and fast.next: fast = fast.next.next next = slow.next slow.next = previous previous, slow = slow, next if fast is not None: slow = slow.next while previous and slow: if previous.val != slow.val: return False previous = previous.next slow = slow.next return True
Complexity Analysis
Time complexity: O(n)
Iterating through half of the linked list to let slow point to the middle and fast point to the end takes O(n/2).
The pointer movements and reversing the left half of the linked list are all O(1) operations.
Iterating through previous and slow also takes half of the linked list, takeing O(n/2) time.
Therefore, the total time complexity is O(n).
Space complexity: O(1)
We create additional three pointers, which takes constraint space.
It won't grow up with the size of the input linked list.
So the total space complexity only takes O(1).
Solution 3: Stack
Algorithm
-
Create a
stacklist to save thenode.valin linked list nodes. -
Iterate through the linked list and append the
node.valto thestacklist. -
Iterate through the linked list again.
If the number isn't equal to the popped number from thestack, it means it's not a palindrome linked list. Return false immediately. -
Return true because the values of the linked list is equal to the popped values from the
stack(the reversed linked list).
Implement
class Solution: def isPalindrome(self, head: Optional[ListNode]) -> bool: stack: list[int] = [] current = head while current is not None: stack.append(current.val) current = current.next current = head while current is not None: if current.val != stack.pop(): return False current = current.next return True
Complexity Analysis
Time complexity: O(n)
Iterate though the linked list twice takes O(2n), which simplifies to O(n).
Space complexity: O(n)
We use an additional list to save the node.val in the linked list, taking O(n) space.