本文已参与「新人创作礼」活动,一起开启掘金创作之路。
题目链接: leetcode.com/problems/pa…
1. 题目介绍
Given the head of a singly linked list, return true if it is a palindrome. 【Translate】:给定单链表的头部,如果是回文则返回真
测试用例:
约束:
期望:
2. 题解
2.1 利用栈来辅助存储并比较
该方法就是通过使用栈来存储Node中的数据,然后依次出栈并与Node比较,缺点是需要N个额外的空间,且用时较长,但思想和语句简单,属于枚举的思想。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public boolean isPalindrome(ListNode head) {
Stack<ListNode> stack = new Stack<ListNode>();
ListNode cur = head;
// 将链表中的数据依次压栈
while(cur != null){
stack.push(cur);
cur = cur.next;
}
// 从头节点开始遍历依次与栈顶元素做比较
while(head != null){
if(head.val != stack.pop().val){
return false;
}
head = head.next;
}
return true;
}
}
2.2 使用快慢指针确定好奇偶的中点
该方法使用快慢指针先确定好奇偶的中点,然后让中点后的右半部分入栈,然后再依次与head比较,这样做就可以节省一半需要操作的空间和时间。
public boolean isPalindrome(ListNode head) {
if (head == null || head.next == null) {
return true;
}
ListNode right = head.next;
ListNode cur = head;
// 先让right来到中点
while(cur.next != null && cur.next.next != null){
right = right.next;
cur = cur.next.next;
}
Stack<ListNode> stack = new Stack<ListNode>();
// 将右半部分压入栈中
while(right != null){
stack.push(right);
right = right.next;
}
while(!stack.isEmpty()){
if(head.val != stack.pop().val){
return false;
}
head = head.next;
}
return true;
}
2.3 不用堆栈的O(1)的方法
首先我们还是通过快慢指针先找到中点,通过快慢指针使得n1为中点,此时让n2变成中点的下一个点,然后让中点指向null,然后定义n3,通过n1,n2,n3的配合依次交换,反转右半部分链表的指向,最后验证完之后,不要忘了把改变的指向恢复成原样。
public boolean isPalindrome3(ListNode head) {
if (head == null || head.next == null) {
return true;
}
ListNode n1 = head;
ListNode n2 = head;
// 让n1来到中点
while(n2.next != null && n2.next.next != null){
n1 = n1.next;
n2 = n2.next.next;
}
n2 = n1.next;
n1.next = null;
ListNode n3 = null;
// 反转右半边链表方向
while(n2 != null){
n3 = n2.next;
n2.next = n1;
n1 = n2;
n2 = n3;
}
n2 = head; // n2指向头节点
n3 = n1; // n3指向最后一个节点
boolean res = true;
while(n2 != null && n3 != null){ // 这里为什么没用(n2.next), 这是为了照顾只有两个数据的情况
if(n2.val != n3.val){
res = false;
break;
}
n2 = n2.next;
n3 = n3.next;
}
n3 = n1;
n2 = n3.next;
n3.next = null;
// 将反转的右半边链表复原
while(n2 != null){
n1 = n2.next;
n2.next = n3;
n3 = n1;
n2 = n1;
}
return res;
}
3. 可参考
[1] while中continue break return各自的作用