https://leetcode.com/problems/palindrome-linked-list/#/description
Given a singly linked list, determine if it is a palindrome.
Follow up:
Could you do it in O(n) time and O(1) space?
Hint:
Two pointer + reverse
Sol:
Time complexity O(n), Space complexity O(n):
Use the fast and slow pointers to find the mid point. Fast pointer moves two moves when slow pointer makes one move. Use stack to record every move the slow pointer moves. When the fast pointer reaches the end, the slow pointer is at the mid point and the first half of the linked list is already in the stack. Then the slow pointer moves on, and compares its value with stack top.
Time complexity O(n), Space complexity O(1):
Find the mid point first and reverse the second half, then compare the first half and the reversed sencond half.
The following codes in space O(1).
# Definition for singly-linked list. # class ListNode(object): # def __init__(self, x): # self.val = x # self.next = None class Solution(object): def isPalindrome(self, head): """ :type head: ListNode :rtype: bool """ # two pointer technique fast = slow = head #find the mid node while fast and fast.next: fast = fast.next.next slow = slow.next # reverse the second half, i.e.reverse slow and node node = None while slow: # make a copy of slow.next before overwrite it # nxt = slow.next, in this prob we do not need to this # reverse slow and slow.next tmp = slow.next slow.next = node # go forward node = slow slow = tmp # comapre the first and second half nodes while node: if node.val != head.val: return False node = node.next head = head.next return True
Note:
1 The fast pointer moves two steps while the slow pointer moves one step at a step, and when the fast pointer stops, the slow pointer is at mid point. Bingo!
2 Q: How to reverse a linked list ?
A:
Step 1: use a tmp varibale to store the next link of current node before overwrite it
tmp = cur.next
Step2 : reverse, let the next link of current node point to the previous node
cur.next = pre
Step 3: Advance
pre = cur
cur = tmp
class ListNode: def __init__(self,x): self.val = x self.next = None def reverseLinkedList(head): if head is None or head.next is None: return head pre = None cur = head h = head while cur: h = cur tmp = cur.next cur.next = pre pre = cur cur = tmp return h
http://blog.csdn.net/u011608357/article/details/36933337
P.S. Do not dig too deep. ugh.
Similar problem:
Singly Linked List Cycle Check - SOLUTION¶
Problem
Given a singly linked list, write a function which takes in the first node in a singly linked list and returns a boolean indicating if the linked list contains a "cycle".
A cycle is when a node's next point actually points back to a previous node in the list. This is also sometimes known as a circularly linked list.
You've been given the Linked List Node class code:
class Node(object):
def __init__(self,value):
self.value = value
self.nextnode = None
Solution
To solve this problem we will have two markers traversing through the list. marker1 and marker2. We will have both makers begin at the first node of the list and traverse through the linked list. However the second marker, marker2, will move two nodes ahead for every one node that marker1 moves.
By this logic we can imagine that the markers are "racing" through the linked list, with marker2 moving faster. If the linked list has a cylce and is circularly connected we will have the analogy of a track, in this case the marker2 will eventually be "lapping" the marker1 and they will equal each other.
If the linked list has no cycle, then marker2 should be able to continue on until the very end, never equaling the first marker.
Let's see this logic coded out:
def cycle_check(node): # Begin both markers at the first node marker1 = node marker2 = node # Go until end of list while marker2 != None and marker2.nextnode != None: # Note marker1 = marker1.nextnode marker2 = marker2.nextnode.nextnode # Check if the markers have matched if marker2 == marker1: return True # Case where marker ahead reaches the end of the list return False
Test Your Solution
"""
RUN THIS CELL TO TEST YOUR SOLUTION
"""
from nose.tools import assert_equal
# CREATE CYCLE LIST
a = Node(1)
b = Node(2)
c = Node(3)
a.nextnode = b
b.nextnode = c
c.nextnode = a # Cycle Here!
# CREATE NON CYCLE LIST
x = Node(1)
y = Node(2)
z = Node(3)
x.nextnode = y
y.nextnode = z
#############
class TestCycleCheck(object):
def test(self,sol):
assert_equal(sol(a),True)
assert_equal(sol(x),False)
print "ALL TEST CASES PASSED"
# Run Tests
t = TestCycleCheck()
t.test(cycle_check)
Good Job!