题目
给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false 。
示例:
思路一:将值赋值到数组中后用双指针法
代码
/**
* 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) {
List<Integer> res = new ArrayList<>();
ListNode temp = head;
//将值赋值到数组中
while(temp != null){
res.add(temp.val);
temp = temp.next;
}
int left = 0;
int right = res.size() - 1;
while(left < right){
if(!res.get(left).equals(res.get(right))){
return false;
}
left++;
right--;
}
return true;
}
}
思路二:将链表的后半部分反转(修改链表结构),然后将前半部分和后半部分进行比较。比较完成后我们应该将链表恢复原样
步骤一:找到前半部分链表的尾节点。
可以计算链表节点的数量,然后遍历链表找到前半部分的尾节点。
也可以****使用快慢指针在一次遍历中找到:慢指针一次走一步,快指针一次走两步,快慢指针同时出发。当快指针移动到链表的末尾时,慢指针恰好到链表的中间。通过慢指针将链表分为两部分。(good idea)
若链表有奇数个节点,则中间的节点应该看作是前半部分。
反转后半部分链表。
判断是否回文。
恢复链表。
返回结果
/**
* 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 firstHalf = findEnd(head);
ListNode SecondHalf = reverseList(firstHalf.next);
//判断是否回文
ListNode p = head;
ListNode q = SecondHalf;
while(q != null){
if(p.val != q.val){
return false;
}
p = p.next;
q = q.next;
}
// 恢复链表
firstHalf.next = reverseList(SecondHalf);
return true;
}
// 前半部分链表的尾节点
public ListNode findEnd(ListNode head){
ListNode slow = head;
ListNode fast = head;
while(fast.next != null && fast.next.next != null){
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
//反转后半部分链表
public ListNode reverseList(ListNode head){
ListNode cur = head;
ListNode pre = null;
ListNode temp;
while(cur != null){
temp = cur.next;
cur.next = pre;
pre = cur;
cur = temp;
}
return pre;
}