要求:
编写一个函数,检查输入的链表是否是回文的。
示例 1:
输入: 1->2
输出: false
示例 2:
输入: 1->2->2->1
输出: true
进阶:
你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/palindrome-linked-list-lcci
初级解法:
不考虑空间和时间复杂的情况下,可以遍历链表,将val存入List数组中,然后头增尾减两个方向进行对比。
进阶要求:
使用快慢指针定位中间节点,将后半段链表进行反转,然后遍历对比,时间复杂度为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) {
//预处理null和只有一个节点的简单情况
if(head == null) return true;
if(head.next == null) return true;
//快慢指针定位中间节点
ListNode fast = head;
ListNode slow = head;
while(fast.next != null && fast.next.next != null){
slow = slow.next;
fast = fast.next.next;
}
//反转链表方法有两种,一种是改变原链表指向,另一种是头插法创建新的一个链表
ListNode half = headInsert(slow);
//ListNode half = reverseNode(slow);
//对比val值
while(head != null){
if(head.val != half.val){
return false;
}
half = half.next;
head = head.next;
}
return true;
}
public ListNode reverseNode(ListNode head){
//预置一个头节点为null,因为第一次反转后为链表的尾部的next属性为null
ListNode pre = null;
ListNode cur = head;
while(cur != null){
//保存next信息
ListNode curNext = cur.next;
//next指向pre,然后pre和cur分别向后移动进行下一步反转
cur.next = pre;
pre = cur;
cur = curNext;
}
return pre;
}
public ListNode headInsert(ListNode head){
ListNode retNode = null;
while(head != null){
//保存next信息
ListNode headNext = head.next;
//已有链表被连接在新插入的next
head.next = retNode;
//已有链表头更新为已插入的最新节点
retNode = head;
//指针指向已保存的next信息
head = headNext;
}
return retNode;
}
}