数据结构与算法面试题:实现一个函数,判断一个链表是否为回文链表。(提示:反转后半部分链表比对前半部分)
简介:数据结构与算法面试题:实现一个函数,判断一个链表是否为回文链表。(提示:反转后半部分链表比对前半部分)
算法思路
算法思路如下:
- 首先需要找到链表的中间节点,可以使用快慢指针来寻找。通过设置两个指针slow和fast,初始时都指向链表头节点。然后将slow向前移动一步,将fast向前移动两步。当fast到达链表尾部时,slow就会指向链表的中心节点。
- 反转链表的后半部分。从slow开始遍历后半部分链表,通过依次将每个节点插入到slow之前,即可实现反转链表的功能。
- 比较链表前半部分和后半部分是否相同。从链表头开始,和反转后的链表后半部分(即slow后面的部分)进行比较,如果全部相同,则说明链表为回文链表。
c++代码实现如下:
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: bool isPalindrome(ListNode* head) { if (head == NULL || head->next == NULL) return true; // 链表为空或只有一个节点,直接返回true ListNode* slow = head; // 慢指针初始指向链表头节点 ListNode* fast = head; // 快指针初始指向链表头节点 while (fast->next != NULL && fast->next->next != NULL) { // 通过快慢指针找到链表中心位置 slow = slow->next; fast = fast->next->next; } ListNode* p = slow->next; // p指向链表后半部分的第一个节点 slow->next = NULL; // 将链表分为前后两个部分,slow为前半部分的最后一个节点,将其next置为NULL ListNode* q = NULL; while (p != NULL) { // 反转链表的后半部分 ListNode* temp = p->next; p->next = q; q = p; p = temp; } p = head; // p重新指向链表头节点,q指向反转后的链表头节点 while (q != NULL) { // 比较链表前半部分和后半部分是否相同 if (p->val != q->val) return false; p = p->next; q = q->next; } return true; } };
- Java面试题
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ class Solution { public boolean isPalindrome(ListNode head) { if (head == null || head.next == null) return true; // 链表为空或只有一个节点,直接返回true ListNode slow = head; ListNode fast = head; while (fast != null && fast.next != null) { // 通过快慢指针找到链表中心位置 slow = slow.next; fast = fast.next.next; } ListNode p = reverse(slow); // 反转链表的后半部分并返回头节点 ListNode q = head; while (p != null) { // 比较链表前半部分和反转后的链表后半部分是否相同 if (q.val != p.val) return false; q = q.next; p = p.next; } return true; } private ListNode reverse(ListNode head) { // 反转链表 ListNode p = null; ListNode q = head; while (q != null) { ListNode temp = q.next; q.next = p; p = q; q = temp; } return p; } }