力扣网 题目 链接
https://leetcode-cn.com/problems/palindrome-linked-list/
对应官方解答 链接
https://leetcode-cn.com/problems/palindrome-linked-list/solution/hui-wen-lian-biao-by-leetcode-solution/
我自己 对 官方的代码 方法三的理解,
1.里面有 idea软件 调试 代码(可构造链表 输入,打印链表 输出 核对);
2.在官方代码 上 加了详细注释, 为什么这么写;
3.自己按思路写 后 加了详细注释,一些 易坑 的 加了注释说明
本文主要是 官方的代码 方法三的理解
1.以下是 官方代码 的基础上 加注释
class Solution {
public boolean isPalindrome(ListNode head) {
if (head == null) {
return true;
}
// 找到前半部分链表的尾节点并反转后半部分链表
ListNode firstHalfEnd = endOfFirstHalf(head);
ListNode secondHalfStart = reverseList(firstHalfEnd.next);
//**是因为反转后???(firstHalfEnd.next).next 即 "head".next 会变为 null, 因为链表 已经是反向的了
//**所以才反转后半部分链表,而不是反转整个链表。。。。。应该是吧,反转后,firstHalfEnd.next.next=null
//[1,2,2,1]---[2(firstHalfEnd),2,1]---[1,2](secondHalfStart)
//[1,2,3,2,1]---[3(firstHalfEnd),2,1]---[1,2](secondHalfStart)
//反转后,head 链表 【1,2,2,1】-----【1,2,2】 【1,2,3,2,1】-----【1,2,3,2】
// 判断是否回文
ListNode p1 = head;
ListNode p2 = secondHalfStart;
boolean result = true;
while (result && p2 != null) {
if (p1.val != p2.val) {
result = false;
}
p1 = p1.next;
p2 = p2.next;
}
// 还原链表并返回结果 【2,1】
firstHalfEnd.next = reverseList(secondHalfStart); //反转后, secondHalfStart.next=null
//【1,2,+2,1】 【1,2,3,+2,1】
return result;
}
private ListNode reverseList(ListNode head) {
ListNode prev = null;
ListNode curr = head;
while (curr != null) {
ListNode nextTemp = curr.next;
curr.next = prev;
prev = curr;
curr = nextTemp;
}
return prev;
}
private ListNode endOfFirstHalf(ListNode head) {
ListNode fast = head;
ListNode slow = head;
while (fast.next != null && fast.next.next != null) {
fast = fast.next.next;
slow = slow.next;
}
return slow;
}
}
2.以下是 自己理解写代码 的基础上 加注释
class Solution{
public boolean isPalindrome(ListNode head){
if(head==null || head.next==null) return true;
//ListNode headCopy=head;
ListNode slow=head,fast=head;
while(fast!=null && fast.next!=null){
slow=slow.next;
fast=fast.next.next;
}
if(fast!=null) slow=slow.next;
//奇数的时候 ,变成后半部分【1,2,1,2,1】--【2(slow),1】
//【1,2,2,1】--【2(slow),1】
//ListNode reversal=reverse(headCopy);
//里面 的链表 改变了 指针方向 ,即使 是 Copy 的链表节点 (存的是链表中 节点地址) 也没用,
//不像 前面的 slow=slow.next , 只对 Copy 的链表节点 附上 不同的 节点地址,
// *没有对 head 里 的 本质 的链表 进行修改。。。
//函数运行后,headCopy.next=null,即 head.next=null // 因为链表 已经是反向的了
//所以 要选择 后半部分 反转,不然 整个链表 数据 找不回来了,后面无法判断
ListNode reversal=reverse(slow); //函数运行后,slow.next=
//复原 head
ListNode headCopy2=head;
ListNode reversalCopy=reversal;
while(headCopy2.val==reversalCopy.val){
headCopy2=headCopy2.next;
reversalCopy=reversalCopy.next;
if(reversalCopy==null) break; //head 会多出一个(偶数时)或两个(奇数时) ,
//因为slow.next=null,slow!=null
}
//slow.next=reverse(reversal);//由上可知,只能放在 得出结果的后面(程序最后) 【1,2,1,2,+2,1】【1,2,2,+2,1】
//这句是错的,2,+2,自己指向自己,无限循环
slow=reverse(reversal);//这句才对 最后结果:【1,2,1,2,+1】【1,2,2,+1】
if(reversalCopy==null) return true;
/* //不复原 head
while(head.val==reversal.val){
head=head.next;
reversal=reversal.next;
if(reversal==null) return true; //head 会多出一个(偶数时)或两个(奇数时) ,
//因为slow.next=null,slow!=null
}*/
return false;
}
public ListNode reverse(ListNode cur){
ListNode pre=null;
while(cur!=null){
ListNode curNext=cur.next;
cur.next=pre;
pre=cur;
cur=curNext;
}
return pre;
}
}
3.以下是 (IDEA软件 调试–(复原链表))自己理解写代码 的基础上 加注释
package com.lxtm.settings.test;
import com.lxtm.crm.utils.DateTimeUtil;
import com.lxtm.crm.utils.MD5Util;
class ListNode{
public Integer val;
public ListNode next;
public ListNode(int a) {
this.val = a;
}
}
public class Test1 {
public static void print(ListNode a){
while (a!=null){
System.out.println(a.val);
a=a.next;
}
}
public static boolean isPalindrome(ListNode head){
if(head==null || head.next==null) return true;
ListNode headCopy=head;
ListNode slow=head,fast=head;
while(fast!=null && fast.next!=null){
slow=slow.next;
fast=fast.next.next;
}
if(fast!=null) slow=slow.next; //奇数的时候
ListNode reversal=reverse(slow); //函数运行后,headCopy==reversal
//[2,1] //[2,null]
print(reversal);
System.out.println("---");
//复原 head
ListNode headCopy2=head;
ListNode reversalCopy=reversal;
while(headCopy2.val==reversalCopy.val){
headCopy2=headCopy2.next;
reversalCopy=reversalCopy.next;
if(reversalCopy==null) break; //head 会多出一个(偶数时)或两个(奇数时) ,
//因为slow.next=null,slow!=null
}
print(reversal); //[1,2]
System.out.println("====");
//show [2,null]
//slow.next=reverse(reversal);//由上可知,只能放在 得出结果的后面(程序最后)
//[1,2] ---[2,1] 这句就是 自己指向自己,无限循环
slow=reverse(reversal); //这样才对,恢复了,1,1,2,1
print(head);
if(reversalCopy==null) return true;
//不复原的
// while(headCopy.val==reversal.val){
// headCopy=headCopy.next;
// reversal=reversal.next;
// if(reversal==null) return true;
// }
return false;
}
public static ListNode reverse(ListNode cur){
ListNode pre=null;
while(cur!=null){
ListNode curNext=cur.next;
cur.next=pre;
pre=cur;
cur=curNext;
}
return pre;
}
public static void main(String[] args) {
ListNode head=new ListNode(1);
head.next=new ListNode(1);
head.next.next=new ListNode(2);
head.next.next.next=new ListNode(1);
print(head);
System.out.println("----------");
if(isPalindrome(head)) System.out.println("true");
else System.out.println("false");
}
}
4.以下是 (IDEA软件 调试–(不复原链表))自己理解写代码 的基础上 加注释
package com.lxtm.settings.test;
import com.lxtm.crm.utils.DateTimeUtil;
import com.lxtm.crm.utils.MD5Util;
class ListNode{
public Integer val;
public ListNode next;
public ListNode(int a) {
this.val = a;
}
}
public class Test1 {
public static void print(ListNode a){
while (a!=null){
System.out.println(a.val);
a=a.next;
}
}
public static boolean isPalindrome(ListNode head){
if(head==null || head.next==null) return true;
ListNode headCopy=head;
ListNode slow=head,fast=head;
while(fast!=null && fast.next!=null){
slow=slow.next;
fast=fast.next.next;
}
if(fast!=null) slow=slow.next; //奇数的时候
ListNode reversal=reverse(slow); //函数运行后,headCopy==reversal
print(reversal);
System.out.println("---");
print(head);
while(headCopy.val==reversal.val){
headCopy=headCopy.next;
reversal=reversal.next;
if(reversal==null) return true;
}
return false;
}
public static ListNode reverse(ListNode head){
ListNode pre=null,cur=head;
while(cur!=null){
ListNode curNext=cur.next;
cur.next=pre;
pre=cur;
cur=curNext;
}
return pre;
}
public static void main(String[] args) {
ListNode head=new ListNode(1);
head.next=new ListNode(1);
head.next.next=new ListNode(2);
head.next.next.next=new ListNode(1);
print(head);
System.out.println("----------");
if(isPalindrome(head)) System.out.println("true");
else System.out.println("false");
}
}