数据结构与算法面试题:实现一个函数,判断一个链表是否为回文链表。(提示:反转后半部分链表比对前半部分)
简介:数据结构与算法面试题:实现一个函数,判断一个链表是否为回文链表。(提示:反转后半部分链表比对前半部分)
算法思路
算法思路如下:
-
首先需要找到链表的中间节点,可以使用快慢指针来寻找。通过设置两个指针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;
}
}