关键点:
- 方法1:利用栈 T= O(N) S = O(N)
- //将链表压入栈,利用栈的先进后出逆序出链表对比原链表各节点值
- 方法2:利用栈 T= O(N) S = O(N/2)
- //将链表后半段压入栈,逆序后半段 与前半段链表值比较
- 方法3:仅用指针 T= O(N) S = O(1)
- //将链表后半段反转,后半段 与前半段链表值比较,然后将后半段链表恢复
//方法1:利用栈 T= O(N) S = O(N)
//将链表压入栈,利用栈的先进后出逆序出链表对比原链表各节点值
public static boolean isPalindome1(Node head) {
if(head == null || head.next == null) return true;
Stack<Node> s = new Stack<Node>();
Node cur = head;
while(cur != null) {
s.push(cur);
cur = cur.next;
}
cur = head;
while(!s.isEmpty()) {
if(s.pop().value != cur.value) return false;
cur = cur.next;
}
return true;
}
//方法2:利用栈 T= O(N) S = O(N/2)
//将链表后半段压入栈,逆序后半段 与前半段链表值比较
public static boolean isPalindome2(Node head) {
if(head == null || head.next == null) return true;
Stack<Node> s = new Stack<Node>();
//1、找到中节点 利用快慢指针 slow指针到达中节点
Node fast = head;
Node slow = head;
while(fast.next != null && fast.next.next != null) {
fast = fast.next.next;
slow = slow.next;
}
//2、后半段压栈
Node cur = slow.next;
while(cur != null) {
s.push(cur);
cur = cur.next;
}
//3、比较前半段与后半段
cur = head;
while(!s.isEmpty()) {
if(s.pop().value != cur.value) return false;
cur = cur.next;
}
return true;
}
//方法3:仅用指针 T= O(N) S = O(1)
//将链表后半段反转,后半段 与前半段链表值比较,然后将后半段链表恢复
public static boolean isPalindome3(Node head) {
if(head == null || head.next == null) return true;
//1、找到中节点 利用快慢指针 slow指针到达中节点
Node fast = head;
Node slow = head;
while(fast.next != null && fast.next.next != null) {
fast = fast.next.next;
slow = slow.next;
}
//2、后半段反转
Node pre = slow;
Node cur = slow.next;
Node next = null;
pre.next = null;//中间节点指向null
while(cur != null) {
next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
}
Node last = pre;//记录终结点 以便后期恢复使用
//3、比较前半段与后半段,检查回文
//后半段头结点为pre
cur = head;
while(cur != null && pre != null) {
if(cur.value != pre.value) return false;
cur = cur.next;
pre = pre.next;
}
//4、恢复后半段链表
pre = last;
cur = pre.next;
while(cur != null) {
next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
}
return true;
}