เมื่อต้องการตรวจสอบว่า Singly Linked List เป็น Palindrome (อ่านจากหน้าหลังได้เหมือนกัน) หรือไม่ สามารถเปรียบเทียบโหนดแรกกับโหนดสุดท้าย แล้วเลื่อนเข้ามาเรื่อยๆ
โค้ดตัวอย่าง
class Node:
def __init__(self, data):
self.data = data
self.next = None
class LinkedList_struct:
def __init__(self):
self.head = None
self.last_node = None
def add_elements(self, data):
if self.last_node is None:
self.head = Node(data)
self.last_node = self.head
else:
self.last_node.next = Node(data)
self.last_node = self.last_node.next
def get_previous_node(self, ref_node):
curr = self.head
while curr and curr.next != ref_node:
curr = curr.next
return curr
def check_palindrome(my_list):
beg = my_list.head
end = my_list.last_node
while beg != end and end.next != beg:
if beg.data != end.data:
return False
beg = beg.next
end = my_list.get_previous_node(end)
return True
my_instance = LinkedList_struct()
my_input = input('Enter elements to the linked list: ').split()
for data in my_input:
my_instance.add_elements(int(data))
if check_palindrome(my_instance):
print('The linked list is palindromic in nature')
else:
print('The linked list is not palindromic in nature')
ผลลัพธ์
Enter elements to the linked list: 89 90 78 90 89 The linked list is palindromic in nature
คำอธิบาย
คลาส
NodeและLinkedList_structเหมือนตัวอย่างก่อนหน้าเมธอด
get_previous_node: หาโหนดก่อนหน้าของ ref_node โดย traverse จาก head (O(n))ฟังก์ชัน
check_palindrome: ใช้ two pointers (beg จากหน้า, end จากหลัง) เปรียบเทียบค่า แล้วเลื่อน beg ไปข้างหน้า, end ไปข้างหลัง (ผ่าน get_previous_node)เงื่อนไขหยุด:
beg != end and end.next != begครอบคลุมทั้งกรณีจำนวนโหนดคู่และคี่
ข้อจำกัด: วิธีนี้ใช้เวลา O(n²) เพราะ get_previous_node ใช้ O(n) เรียกซ้ำ n/2 ครั้ง
วิธีที่ดีกว่า (O(n) time, O(1) space):
- หาจุดกลางด้วย slow/fast pointer
- Reverse ครึ่งหลังของ linked list
- เปรียบเทียบครึ่งหน้ากับครึ่งหลังที่ reverse แล้ว
- Reverse กลับคืนเพื่อคืนสภาพเดิม (optional)