给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false 。
示例 1:
输入:head = [1,2,2,1]
输出:true
示例 2:
输入:head = [1,2]
输出:false
提示:
链表中节点数目在范围[1, 105] 内
0 <= Node.val <= 9
进阶:你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/palindrome-linked-list
解法1:没有参考解法,最粗糙的解答方法:
/**
* 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 {
//最初想到的方案:
//时间复杂度 :o(n) 空间复杂度 o(n)
//
public boolean isPalindrome(ListNode head) {
//找到head的长度
ListNode first = head;
ListNode center = head;
int length = 0;
Stack<Integer> stack = new Stack<>();
while(first != null){
length++;
stack.push(first.val);
first=first.next;
}
int centerLength = length/2;
int count = 0;
//判断长度是偶数还是奇数
boolean isOu = length%2 == 0;
while(center != null){
Integer temp = stack.pop();
if(isOu && count >= centerLength){
if(center.val != temp){
return false;
}
} else if(!isOu && count >= centerLength+1){
if(center.val != temp){
return false;
}
}
count++;
center = center.next;
}
return stack.isEmpty();
}
}
这里借助了额外的存储空间,所以空间复杂度是O(n),循环了两次所以时间复杂度是O(n)
那么我们想想怎么能够优化空间复杂度呢?
主要问题是怎么获取到中间节点
我们可以死记硬背住获取中间节点的方法:
ListNode center = head;
ListNode fast = head;
while(fast.next != null && fast.next.next != null){
fast = fast.next.next;
center = center.next;
}
如果已知中间节点,那就可以将中间节点之前的链表翻转,再跟中间节点之后的链表对比,就可以了。
好了,现在的问题简化为链表翻转问题。
public ListNode reverseList(ListNode head){
ListNode reverse = null;
while(head != null){
ListNode temp = head;
head = head.next;
temp.next = reverse;
reverse = temp;
}
return reverse;
}
那最后可以得出解法:
/**
* 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) {
//得到中间节点
ListNode center = head;
ListNode fast = head;
while(fast.next != null && fast.next.next != null){
fast = fast.next.next;
center = center.next;
}
//链表翻转
ListNode reverse = reverseList(center);
//判断节点是否相同
while(head != null && reverse != null){
if(head.val != reverse.val){
return false;
}
head = head.next;
reverse = reverse.next;
}
return true;
}
public ListNode reverseList(ListNode head){
ListNode reverse = null;
while(head != null){
ListNode temp = head;
head = head.next;
temp.next = reverse;
reverse = temp;
}
return reverse;
}
}
时间复杂度为O(n) 空间复杂度为O(1)