📌  相关文章
📜  检查单链表是否为回文的Python程序

📅  最后修改于: 2022-05-13 01:55:31.205000             🧑  作者: Mango

检查单链表是否为回文的Python程序

给定一个单链字符列表,编写一个函数,如果给定列表是回文,则返回 true,否则返回 false。

回文链表

方法1(使用堆栈):

  • 一个简单的解决方案是使用一堆列表节点。这主要涉及三个步骤。
  • 从头到尾遍历给定列表,并将每个访问的节点推送到堆栈。
  • 再次遍历列表。对于每个访问的节点,从堆栈中弹出一个节点,并将弹出节点的数据与当前访问的节点进行比较。
  • 如果所有节点都匹配,则返回 true,否则返回 false。

下图是上述方法的试运行:

以下是上述方法的实现:

Python3
# Python3 program to check if linked
# list is palindrome using stack
class Node:
    def __init__(self, data):        
        self.data = data
        self.ptr = None
          
# Function to check if the linked list
# is palindrome or not
def ispalindrome(head):
      
    # Temp pointer
    slow = head
  
    # Declare a stack
    stack = []
      
    ispalin = True
  
    # Push all elements of the list
    # to the stack
    while slow != None:
        stack.append(slow.data)
          
        # Move ahead
        slow = slow.ptr
  
    # Iterate in the list again and
    # check by popping from the stack
    while head != None:
  
        # Get the top most element
        i = stack.pop()
          
        # Check if data is not
        # same as popped element
        if head.data == i:
            ispalin = True
        else:
            ispalin = False
            break
  
        # Move ahead
        head = head.ptr
          
    return ispalin
  
# Driver Code
  
# Addition of linked list
one = Node(1)
two = Node(2)
three = Node(3)
four = Node(4)
five = Node(3)
six = Node(2)
seven = Node(1)
  
# Initialize the next pointer
# of every current pointer
one.ptr = two
two.ptr = three
three.ptr = four
four.ptr = five
five.ptr = six
six.ptr = seven
seven.ptr = None
  
# Call function to check 
# palindrome or not
result = ispalindrome(one)
  
print("isPalindrome:", result)
  
# This code is contributed by Nishtha Goel


Python3
# Python program to check if
# linked list is palindrome
  
# Node class
class Node:
  
    # Constructor to initialize
    # the node object
    def __init__(self, data):        
        self.data = data
        self.next = None
  
class LinkedList:
  
    # Function to initialize head
    def __init__(self):        
        self.head = None
  
    # Function to check if given
    # linked list is pallindrome or not
    def isPalindrome(self, head):        
        slow_ptr = head
        fast_ptr = head
        prev_of_slow_ptr = head
          
        # To handle odd size list
        midnode = None
          
        # Initialize result
        res = True  
          
        if (head != None and 
            head.next != None):
              
            # Get the middle of the list. 
            # Move slow_ptr by 1 and 
            # fast_ptrr by 2, slow_ptr 
            # will have the middle node
            while (fast_ptr != None and 
                   fast_ptr.next != None):
                        
                # We need previous of the slow_ptr 
                # for linked lists  with odd 
                # elements
                fast_ptr = fast_ptr.next.next
                prev_of_slow_ptr = slow_ptr
                slow_ptr = slow_ptr.next
                  
            # fast_ptr would become NULL when 
            # there are even elements in the 
            # list and not NULL for odd elements. 
            # We need to skip the middle node for 
            # odd case and store it somewhere so 
            # that we can restore the original list
            if (fast_ptr != None):
                midnode = slow_ptr
                slow_ptr = slow_ptr.next
                  
            # Now reverse the second half 
            # and compare it with the first half
            second_half = slow_ptr
              
            # NULL terminate first half
            prev_of_slow_ptr.next = None 
              
            # Reverse the second half
            second_half = self.reverse(second_half) 
              
            # Compare
            res = self.compareLists(head, second_half)  
              
            # Construct the original list back
            # Reverse the second half again
            second_half = self.reverse(second_half)
              
            if (midnode != None):
                  
                # If there was a mid node (odd size
                # case) which was not part of either
                # first half or second half.
                prev_of_slow_ptr.next = midnode
                midnode.next = second_half
            else:
                prev_of_slow_ptr.next = second_half
        return res
      
    # Function to reverse the linked list 
    # Note that this function may change 
    # the head
    def reverse(self, second_half):
          
        prev = None
        current = second_half
        next = None
          
        while current != None:
            next = current.next
            current.next = prev
            prev = current
            current = next
              
        second_half = prev
        return second_half
  
    # Function to check if two input 
    # lists have same data
    def compareLists(self, head1, head2):
          
        temp1 = head1
        temp2 = head2
          
        while (temp1 and temp2):
            if (temp1.data == temp2.data):
                temp1 = temp1.next
                temp2 = temp2.next
            else:
                return 0
                  
        # Both are empty return 1
        if (temp1 == None and temp2 == None):
            return 1
              
        # Will reach here when one is NULL
        # and other is not
        return 0
      
    # Function to insert a new node
    # at the beginning
    def push(self, new_data):
          
        # Allocate the Node &
        # Put in the data
        new_node = Node(new_data)
          
        # Link the old list off the new one
        new_node.next = self.head
          
        # Move the head to point to the 
        # new Node
        self.head = new_node
  
    # A utility function to print
    # a given linked list 
    def printList(self):
          
        temp = self.head
          
        while(temp):
            print(temp.data, end = "->")
            temp = temp.next
              
        print("NULL")
  
# Driver code
if __name__ == '__main__':    
    l = LinkedList()
    s = ['a', 'b', 'a', 
         'c', 'a', 'b', 'a']
      
    for i in range(7):
        l.push(s[i])
        l.printList()
          
        if (l.isPalindrome(l.head) != False):
            print("Is Palindrome")
        else:
            print("Not Palindrome")
        print()
  
# This code is contributed by MuskanKalra1


输出:

isPalindrome: true

时间复杂度: O(n)。

方法 2(通过反转列表):
此方法需要 O(n) 时间和 O(1) 额外空间。
1)获取链表的中间。
2)反转链表的后半部分。
3)检查前半部分和后半部分是否相同。
4)通过再次反转后半部分并将其附加回前半部分来构造原始链表

要将列表分成两半,使用本文的方法 2。

当多个节点是偶数时,前半部分和后半部分正好包含半个节点。这种方法的挑战在于处理节点数为奇数的情况。我们不希望中间节点作为列表的一部分,因为我们将比较它们是否相等。对于奇怪的情况,我们使用单独的变量“中间节点”。

Python3

# Python program to check if
# linked list is palindrome
  
# Node class
class Node:
  
    # Constructor to initialize
    # the node object
    def __init__(self, data):        
        self.data = data
        self.next = None
  
class LinkedList:
  
    # Function to initialize head
    def __init__(self):        
        self.head = None
  
    # Function to check if given
    # linked list is pallindrome or not
    def isPalindrome(self, head):        
        slow_ptr = head
        fast_ptr = head
        prev_of_slow_ptr = head
          
        # To handle odd size list
        midnode = None
          
        # Initialize result
        res = True  
          
        if (head != None and 
            head.next != None):
              
            # Get the middle of the list. 
            # Move slow_ptr by 1 and 
            # fast_ptrr by 2, slow_ptr 
            # will have the middle node
            while (fast_ptr != None and 
                   fast_ptr.next != None):
                        
                # We need previous of the slow_ptr 
                # for linked lists  with odd 
                # elements
                fast_ptr = fast_ptr.next.next
                prev_of_slow_ptr = slow_ptr
                slow_ptr = slow_ptr.next
                  
            # fast_ptr would become NULL when 
            # there are even elements in the 
            # list and not NULL for odd elements. 
            # We need to skip the middle node for 
            # odd case and store it somewhere so 
            # that we can restore the original list
            if (fast_ptr != None):
                midnode = slow_ptr
                slow_ptr = slow_ptr.next
                  
            # Now reverse the second half 
            # and compare it with the first half
            second_half = slow_ptr
              
            # NULL terminate first half
            prev_of_slow_ptr.next = None 
              
            # Reverse the second half
            second_half = self.reverse(second_half) 
              
            # Compare
            res = self.compareLists(head, second_half)  
              
            # Construct the original list back
            # Reverse the second half again
            second_half = self.reverse(second_half)
              
            if (midnode != None):
                  
                # If there was a mid node (odd size
                # case) which was not part of either
                # first half or second half.
                prev_of_slow_ptr.next = midnode
                midnode.next = second_half
            else:
                prev_of_slow_ptr.next = second_half
        return res
      
    # Function to reverse the linked list 
    # Note that this function may change 
    # the head
    def reverse(self, second_half):
          
        prev = None
        current = second_half
        next = None
          
        while current != None:
            next = current.next
            current.next = prev
            prev = current
            current = next
              
        second_half = prev
        return second_half
  
    # Function to check if two input 
    # lists have same data
    def compareLists(self, head1, head2):
          
        temp1 = head1
        temp2 = head2
          
        while (temp1 and temp2):
            if (temp1.data == temp2.data):
                temp1 = temp1.next
                temp2 = temp2.next
            else:
                return 0
                  
        # Both are empty return 1
        if (temp1 == None and temp2 == None):
            return 1
              
        # Will reach here when one is NULL
        # and other is not
        return 0
      
    # Function to insert a new node
    # at the beginning
    def push(self, new_data):
          
        # Allocate the Node &
        # Put in the data
        new_node = Node(new_data)
          
        # Link the old list off the new one
        new_node.next = self.head
          
        # Move the head to point to the 
        # new Node
        self.head = new_node
  
    # A utility function to print
    # a given linked list 
    def printList(self):
          
        temp = self.head
          
        while(temp):
            print(temp.data, end = "->")
            temp = temp.next
              
        print("NULL")
  
# Driver code
if __name__ == '__main__':    
    l = LinkedList()
    s = ['a', 'b', 'a', 
         'c', 'a', 'b', 'a']
      
    for i in range(7):
        l.push(s[i])
        l.printList()
          
        if (l.isPalindrome(l.head) != False):
            print("Is Palindrome")
        else:
            print("Not Palindrome")
        print()
  
# This code is contributed by MuskanKalra1 

输出:

a->NULL
Is Palindrome

b->a->NULL
Not Palindrome

a->b->a->NULL
Is Palindrome

c->a->b->a->NULL
Not Palindrome

a->c->a->b->a->NULL
Not Palindrome

b->a->c->a->b->a->NULL
Not Palindrome

a->b->a->c->a->b->a->NULL
Is Palindrome

时间复杂度: O(n)
辅助空间: O(1)

请参阅完整的函数文章来检查单链表是否为回文以获取更多详细信息!