判断一个链表是否为回文结构
(只看黑体字和代码即可)
思路一:把链表节点依次压入栈中,然后依次从栈中拿出节点与链表节点进行比较
// 额外空间复杂度O(n)借助了栈结构
public static boolean function1(Node head) {
Stack<Node> a = new Stack<Node>();
Node help = head;// 复制了一个头节点,指向后面的位置,指的位置在内存中是一致的
while (help != null) {
a.push(help);
help = help.next;
}
while (!a.isEmpty()) {
if (head.value != a.pop().value)
return false;
head = head.next;
}
return true;
}
思路二:设置两个指针,一个为快指针(2V),一个为慢指针(V)。把中间及以后位置压入栈
(两个指针初始位置都是head,当链表节点数为奇数时,如1 2 3 4 5快指针走到位置5,慢指针在位置3。当节点个数为偶数时,
1 2 3 4 5 6,快指针走到5,慢指针走到3.
将3 4 5 6节点压入栈中
然后把栈顶开始与head及next进行比较)
// 借助一半的空间,指针走到一半,把剩下的部分入栈,注意特殊部分的处理,可能head的就是个空值
public static boolean function2(Node head) {
if(head==null||head.next==null) return true;
Node fast = head;
Node slow = head;
Stack<Node> a = new Stack<Node>();
while (fast.next!=null&&fast.next.next != null) {
fast = fast.next.next;
slow = slow.next;
}
while (slow != null) {
a.push(slow);
slow = slow.next;
}
while (!a.isEmpty()) {
if (a.pop().value != head.value)
return false;
head = head.next;
}
return true;
}
进阶:要求链表长度为n时,时间复杂度为O(n),额外空间复杂度为O(1)
思路:同快慢指针,快指针(fast)停止前进时,慢指针(slow)在中间位置(奇数--中间位置,偶数--中间两个位置中的靠前位置)
以slow为头节点,将slow节点以后的进行链表反转
然后从两边向中间遍历。直到从head位置的链表遍历到next为null停止。
返回结论前,将刚刚翻转的一段再翻转回来。
代码:
public static boolean function3(Node head) {
boolean ans=true;
if(head==null||head.next==null) return true;
Node fast=head;
Node slow=head;
while(fast.next!=null&&fast.next.next!=null) {
fast=fast.next.next;
slow=slow.next;
}
//此时slow停留在中间位置,如果是偶数,则是中间位置中的前一个位置
//while后,fast为链表的尾部
while(fast.next!=null) fast=fast.next;
Node h2=reverse(slow);//翻转
//slow.next=null;
//开始遍历,查询
while(head!=null){
if(h2.value!=head.value)
{ans=false;break;}
h2=h2.next;
head=head.next;
}
reverse(fast);//把刚刚翻转过的再转回来,参数:传入头节点
return ans;
}
public static Node reverse(Node head) {
Node pre=null;
Node next=null;
while(head!=null)
{
next=head.next;
head.next=pre;
pre=head;
head=next;//下移一位
}
return pre;
}
(以下分析可略过)
【奇】
———————————————————————————
【偶】从两边对比,遇到3位置时由于其next=null,停止。
当快fast指针停下的时候,还未指到最后一个节点,手动将其指到最后一个节点:
两边开始遍历,A:head为头节点,B:fast为头节点
到head遍历完3位置后停止。(head.value==null)
全部代码:
package Node;
import java.util.Stack;
import Node.ReverseList.Node;
//判断链表是否为回文
public class isPalindrome {
// 链表结构
public static class Node {
int value;
Node next;
Node(int a) {
this.value = a;
}
}
// 额外空间复杂度O(n)借助了栈结构
public static boolean function1(Node head) {
Stack<Node> a = new Stack<Node>();
Node help = head;// 复制了一个头节点,指向后面的位置,指的位置在内存中是一致的
while (help != null) {
a.push(help);
help = help.next;
}
while (!a.isEmpty()) {
if (head.value != a.pop().value)
return false;
head = head.next;
}
return true;
}
// 借助一半的空间,指针走到一半,把剩下的部分入栈,注意特殊部分的处理,可能head的就是个空值
public static boolean function2(Node head) {
if(head==null||head.next==null) return true;
Node fast = head;
Node slow = head;
Stack<Node> a = new Stack<Node>();
while (fast.next!=null&&fast.next.next != null) {
fast = fast.next.next;
slow = slow.next;
}
while (slow != null) {
a.push(slow);
slow = slow.next;
}
while (!a.isEmpty()) {
if (a.pop().value != head.value)
return false;
head = head.next;
}
return true;
}
public static boolean function3(Node head) {
boolean ans=true;
if(head==null||head.next==null) return true;
Node fast=head;
Node slow=head;
while(fast.next!=null&&fast.next.next!=null) {
fast=fast.next.next;
slow=slow.next;
}
//此时slow停留在中间位置,如果是偶数,则是中间位置中的前一个位置
//fast为链表的尾部
while(fast.next!=null) fast=fast.next;
Node h2=reverse(slow);
//slow.next=null;
//开始遍历,查询
while(head!=null){
if(h2.value!=head.value)
{ans=false;break;}
h2=h2.next;
head=head.next;
}
reverse(fast);//把刚刚反转过的再转回来
return ans;
}
public static Node reverse(Node head) {
Node pre=null;
Node next=null;
while(head!=null)
{
next=head.next;
head.next=pre;
pre=head;
head=next;//下移一位
}
return pre;
}
public static void main(String[] args) {
Node head = null;
printLinkedList(head);
System.out.print(function1(head) + " | ");
System.out.print(function2(head) + " | ");
System.out.println(function3(head) + " | ");
printLinkedList(head);
System.out.println("=========================");
head = new Node(1);
printLinkedList(head);
System.out.print(function1(head) + " | ");
System.out.print(function2(head) + " | ");
System.out.println(function3(head) + " | ");
printLinkedList(head);
System.out.println("=========================");
head = new Node(1);
head.next = new Node(2);
printLinkedList(head);
System.out.print(function1(head) + " | ");
System.out.print(function2(head) + " | ");
System.out.println(function3(head) + " | ");
printLinkedList(head);
System.out.println("=========================");
head = new Node(1);
head.next = new Node(1);
printLinkedList(head);
System.out.print(function1(head) + " | ");
System.out.print(function2(head) + " | ");
System.out.println(function3(head) + " | ");
printLinkedList(head);
System.out.println("=========================");
head = new Node(1);
head.next = new Node(2);
head.next.next = new Node(3);
printLinkedList(head);
System.out.print(function1(head) + " | ");
System.out.print(function2(head) + " | ");
System.out.println(function3(head) + " | ");
printLinkedList(head);
System.out.println("=========================");
head = new Node(1);
head.next = new Node(2);
head.next.next = new Node(1);
printLinkedList(head);
System.out.print(function1(head) + " | ");
System.out.print(function2(head) + " | ");
System.out.println(function3(head) + " | ");
printLinkedList(head);
System.out.println("=========================");
head = new Node(1);
head.next = new Node(2);
head.next.next = new Node(3);
head.next.next.next = new Node(1);
printLinkedList(head);
System.out.print(function1(head) + " | ");
System.out.print(function2(head) + " | ");
System.out.println(function3(head) + " | ");
printLinkedList(head);
System.out.println("=========================");
head = new Node(1);
head.next = new Node(2);
head.next.next = new Node(2);
head.next.next.next = new Node(1);
printLinkedList(head);
System.out.print(function1(head) + " | ");
System.out.print(function2(head) + " | ");
System.out.println(function3(head) + " | ");
printLinkedList(head);
System.out.println("=========================");
head = new Node(1);
head.next = new Node(2);
head.next.next = new Node(3);
head.next.next.next = new Node(4);
head.next.next.next.next = new Node(5);
printLinkedList(head);
System.out.print(function1(head) + " | ");
System.out.print(function2(head) + " | ");
System.out.println(function3(head) + " | ");
printLinkedList(head);
System.out.println("=========================");
}
private static void printLinkedList(Node head) {
while (head != null) {
System.out.print(head.value + ",");
head = head.next;
}
System.out.println();
}
}