面试题:判断一个链表是否为回文结构
面试题:判断一个链表是否为回文结构
这道题,因为需要遍历链表,所以时间复杂度肯定是O(n)的。如果使用空间复杂度为O(n)是非常简单的,无非是遍历一遍链表,将节点保存到数组、List或者栈中,然后判断一次是否回文。但是如何使用常数阶的空间复杂度呢?
public class NC96 {
/**
* 解题思路:
* 这道题目可以将链表中的数值遍历一遍保存到数组中,这样判断回文串是非常的简单的,但是这样操作的空间复杂度是O(n),我觉得应该
* 有其他的优化方式。
*
* 使用快慢指针,快指针的速度是慢指针的两倍,快指针到达链表末尾时,慢指针就是中间位置。
* 将慢指针后面的链表改变方向,并使用链表后半部分跟链表的前半部分对比,如果相同,则是回文,否则不是回文。
* 记着后面还要将链表把方向改回来。
*
* @author freedom wang
* @date 2021-02-06 16:47:33
*/
public boolean isPail(ListNode head) {
// 特殊情况判断
if (head == null || head.next == null) {
return true;
}
// 1. 定义快慢指针,快指针速度为慢指针的两倍,快指针到达末尾,则慢指针为中间
ListNode dummy = new ListNode(-1);
dummy.next = head;
ListNode slow = dummy;
ListNode fast = dummy;
while (fast.next != null) {
fast = fast.next;
if (fast.next != null) {
fast = fast.next;
}
slow = slow.next;
}
// 2. 从慢指针开始反转链表
ListNode reverse = reverse(slow);
// 3. 判断是否回文
boolean isPail = true;
ListNode head1 = head;
ListNode head2 = reverse;
while (head1 != slow && head2 != slow) {
if (head1.val != head2.val) {
isPail = false;
break;
} else {
head1 = head1.next;
head2 = head2.next;
}
}
// 4.将链表反转回去
reverse(reverse);
return isPail;
}
private ListNode reverse(ListNode node) {
if (node == null || node.next == null) {
return node;
}
ListNode pre = null;
ListNode cur = node;
while (cur != null) {
ListNode next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
}
return pre;
}
}