题目
请判断一个链表是否为回文链表。
示例 1:
输入: 1->2
输出: false
示例 2:
输入: 1->2->2->1
输出: true
进阶:
你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?
思路一
将链表的值依次存入列表中再利用双指针法比较是否首尾对应位置的元素值是否相等。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
//将其放入数组中再看是否为回文
public boolean isPalindrome(ListNode head) {
//Step1:判断特殊情况
if(head == null || head.next == null) return true;
//step2:将其放入列表中
ArrayList<Integer> list = new ArrayList<>();
ListNode cur = head;
while(cur != null){
list.add(cur.val);
cur = cur.next;
}
//Step3:采用双指针方式比较是否为回文
int l = 0, r = list.size() - 1;
while(l <= r){
if(!list.get(l).equals(list.get(r))){
return false;
}
l++;r--;
}
//Step4:返回结果
return true;
}
}
思路二
1.先找到链表的中间结点;
2.从中间结点开始返回后一部分链表
3.比较两个链表结点值是否相等
4.恢复原链表
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public boolean isPalindrome(ListNode head) {
//Step1:判断特殊情况
if(head == null || head.next == null) return true;//空链表与只有一个结点
if(head.next.next == null){
return head.val == head.next.val;//仅仅有两个结点
}
//Step2:定义辅助变量,找到中间结点
ListNode fast = head;
ListNode slow = head;
while(fast != null && fast.next != null){
slow = slow.next;
fast = fast.next.next;
}
//Step3:反转后面的结点
fast = reverse(slow);
//step4:定义辅助变量,比较两个链表
ListNode pre = head, last = fast;
boolean flag = true;
while(pre != last){
if(pre.val != last.val){
flag = false;
break;
}
if(pre.next == last) break;//可以写也可以不写
pre = pre.next;
last = last.next;
}
//Step5:恢复链表
reverse(fast);
//Step6:返回结果值
return flag;
}
//反转链表
private ListNode reverse(ListNode head){
if(head == null || head.next == null){
return head;
}
ListNode p = reverse(head.next);
head.next.next = head;
head.next = null;
return p;
}
}