🐕 给你一个单链表的头节点 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) 空间复杂度解决此题?
🐖思路一:
快慢指针 慢指针一次走一步 快指针一次走两步
slow指针 后半段入栈 之后弹出再与前半段比较
如果直到栈为空都相等 证明是回文
上代码
public static boolean isPalindrome(ListNode head) {
if(head == null) {
return true;
}
//快慢指针 慢指针一次走一步 快指针一次走两步
ListNode slow = head;
ListNode fast = head;
while(fast.next != null && fast.next.next != null) {
slow = slow.next;
fast = fast.next.next;
}
//现在slow指针已经到达中点位置 考虑入栈
Stack<ListNode> stack = new Stack<>();
while(slow != null) {
stack.push(slow);
slow = slow.next;
}
//入栈完毕 接下来出栈比较
while(!stack.isEmpty()) {
if(head.val != stack.pop().val) {
return false;
}
head = head.next;
}
return true;
}
🐀思路二:双指针 未复原 只判断版本
快慢指针 慢指针一次走一步 快指针一次走两步
修改slow后半段指针 指向
从尾巴和 head 依次对比 如果不相等 返回 false
上代码
public static boolean isPalindrome_V2(ListNode head) {
if(head == null) {
return true;
}
ListNode slow = head;
ListNode fast = head;
while(fast.next != null && fast.next.next != null) {
fast = fast.next.next;
slow = slow.next;
}
//如果此时链表只有一个数时 return true
if(slow.next == null) {
return true;
}
//先记录temp 为 slow的next ,让slow的next 指向 null
// 让tempNext 为temp的next 让 temp 的next 指向 slow
ListNode temp = slow.next;
slow.next = null;
ListNode tempNext = temp.next;
while(temp != null) {
temp.next = slow;
slow = temp;
temp =tempNext ;
tempNext = tempNext == null ? null:tempNext.next;
}
//此时slow就是尾结点
while(slow != null && head != null) {
if(head.val != slow.val) {
return false;
}
slow = slow.next;
head = head.next;
}
return true;
}
🐇 思路三:双指针 判断且复原版本
双指针 然后反转后半段链表 再从两端一一对比
如果途中有不相等 记录flag = false
如果整个途中没有不相等的 flag = true
然后要把链表还原
上代码
public static boolean isPalindrome_V3(ListNode head) {
if(head == null) {
return true;
}
ListNode slow = head;
ListNode fast = head;
while(fast.next != null && fast.next.next != null) {
fast = fast.next.next;
slow = slow.next;
}
//如果此时链表只有一个数时 return true
if(slow.next == null) {
return true;
}
ListNode mid = slow;//待会复原要用到
//先记录temp 为 slow的next ,让slow的next 指向 null
// 让tempNext 为temp的next 让 temp 的next 指向 slow
ListNode temp = slow.next;
slow.next = null;
ListNode tempNext = temp.next;
while(temp != null) {
temp.next = slow;
slow = temp;
temp =tempNext ;
tempNext = tempNext == null ? null:tempNext.next;
}
//此时slow就是尾结点
ListNode tail = slow; //待会复原要用到
boolean flag = true;
while(slow != null && head != null) {
if(head.val != slow.val) {
flag = false;
break;
}
slow = slow.next;
head = head.next;
}
/*
开始复原后半段
记录 tail.next 为 pre
pre.next 为 prePre
让tail的next 指向 null
*/
ListNode pre = tail.next;
ListNode prePre = pre.next;
tail.next = null;
while(tail != mid) {
pre.next = tail;
tail = pre;
pre = prePre;
prePre = prePre == null ? null : prePre.next;
}
return flag;
}
🐘思路四:递归判断
这里扯一个点:递归打印单向链表…
public static void printNodes(ListNode head) {
if(head == null) {
return;
}
printNodes(head.next);
System.out.println(head.val);
}
上代码
static ListNode temp;
public static boolean isPalindrome_V4(ListNode head) {
temp = head; // temp总是按顺序记录前半段
return check(head);
}
public static boolean check(ListNode head) {
if(head == null) {
return true;
}
// head 会递归至 结尾再判断
boolean res = check(head.next) && (temp.val == head.val);
temp = temp.next;
return res;
}