反转链表的方式
这种方式比较简单,通过创建一个和原链表的逆序的方式,然后逐一进行比较;
boolean isPalindromeReverse(ListNode head){
if(head == null) return false;
ListNode cur = head;
ListNode tmpHead = null;
while(cur!= null) {
ListNode tmp = new ListNode(cur.val);
tmp.next = tmpHead;
tmpHead = tmp;
cur = cur.next;
}
cur = head;
while(cur != null){
if(cur.val != tmpHead.val) return false;
cur = cur.next;
tmpHead = tmpHead.next;
}
return true;
}
栈方式(空间复杂度O(N))
1.利用栈的先进后出的特性,把所有的节点进行入栈,出队列是正好原链表的顺序相反,然后逐一比较
boolean isPalindromeStack(ListNode head) {
Stack<ListNode> stack = new Stack<ListNode>();
ListNode cur = head;
while(cur != null){
stack.push(cur);
cur = cur.next;
}
cur = head;
while(!stack.isEmpty()) {
ListNode tmp = stack.pop();
if(tmp.val != cur.val) return false;
cur = cur.next;
}
return true;
}
栈方式优化(使用一半的存储空间)
1.首先找到链表的中点**(长度为奇数,中点,长度为偶数,取上中点)**
2.将除了中点的剩余元素都进入栈;(之所以这么操作,后半部分入栈,出栈时逆序,出栈时依次和栈的元素一次比较,恰好实现首尾比较)
//首先链表的中点,如果链表长度为奇数返回中点,如果是偶数返回上中点
//然后将链表中点后元素都入栈的结构,
//弹出栈中的元素分别和链表的元素比较
private boolean isPalindromeOptimizeStack(ListNode head) {
if (head == null) return false;
if (head.next == null) return true;
ListNode slow = head, fast = head.next;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
ListNode cur = slow.next;
Stack<ListNode> stack = new Stack();
while (cur != null) {
stack.push(cur);
cur = cur.next;
}
cur = head;
while (!stack.isEmpty()) {
ListNode tmp = stack.pop();
if (tmp.val != cur.val) return false;
}
return true;
}
原地比较(空间复杂度O(1))
1.首先找到链表的中点**(长度为奇数,中点,长度为偶数,取上中点)**
2.这一步不是使用栈的结构实现逆序,而是进行链表的逆序;
3.以mid为起点,对之后的元素进行逆序;
4. 上半部分链表和下部分链表进行逐次比较
5. 对链表修改进行复原;
private boolean isPalindromeLinkedReverse(ListNode head) {
if (head == null) return false;
if (head.next == null) return true;
//链表的中点
ListNode midNode = getMidOrUpMidNode(head);
//链表中点右侧的链表进行反转链表
ListNode pre = midNode;
ListNode curB = midNode.next, next = null;
midNode.next = null; //断开链表
while (curB != null) {
next = curB.next;
curB.next = pre;
pre = curB;
curB = next;
}
//pre执行头节点;
curB = pre;
//比较前后两部分链表元素是否是相等,判断是否是回文结构
ListNode curA = head;
while (curA != null && curB != null) {
if (curA.val != curB.val) return false;
curA = curA.next;
curB = curB.next;
}
//恢复到原来的链表
curB = pre;
pre = null;
while (curB != midNode) {
next = curB.next;
curB.next = pre;
pre = curB;
curB = next;
}
curB.next = pre;
return true;
}