给定一个链表的头节点head,判断是否是回文结构
1->2->1 返回true
进阶: 如果链表长度N,时间复杂度O(N) 额外空间O(1)
方法一
利用栈结构(需要额外空间)
从左到右遍历,一次压栈。 这样的到的 从栈顶到栈底的节点值出现顺序会与原链表从左到右的值出现顺序相反。
废话不多说,上代码:
package TT; import java.util.Stack; public class Test92 { public class Node{ public int value; public Node next; public Node(int data){ this.value = data; } } public static boolean isPalindrome(Node head){ Stack<Node> stack = new Stack<Node>(); Node cur = head; while(cur != null){ stack.push(cur); cur=cur.next; } while(head !=null){ if(head.value !=stack.pop().value){ return false; } head = head.next; } return true; } }
进阶:
方法二 对上面的进行优化,不需要所有的节点都压入栈中 压入一半即可
前 N/2的节点叫做左半区,后N/2叫做右半区。 N为奇数 忽略处于最中间的节点,还是 前 N/2的节点叫做左半区,后N/2叫做右半区
相当于折纸 折回去
package TT; import java.util.Stack; import TT.Test85.Node; public class Test93 { public static boolean isPalindrome2(Node head){ if(head==null || head.next==null){ return true; } Node right = head.next; Node cur = head; while(cur.next != null && cur.next.next != null){ right = right.next; cur=cur.next.next; } Stack<Node> stack = new Stack<Node>(); while(right!=null){ stack.push(right); right=right.next; } while(!stack.isEmpty()){ if(head.value != stack.pop().value){ return false; } head=head.next; } return true; } }
方法三 改变结构 不需要栈和其他数据结构 只用有限几个变量 其额外空间复杂度O(1)
1 首先改变链表右半区的机构 使整个右半区反转 最后指向中间节点 看图一目了然
package TT; import TT.Test84.Node; public class Test94 { public boolean isPalindrome2(Node head){ if(head==null || head.next==null){ return true; } Node n1 = head; Node n2 = head; while(n2.next !=null && n2.next.next != null){ n1=n1.next; n2=n2.next.next; } n2 = n1.next; n1.next=null; Node n3 =null; while(n2 != null){ n3=n2.next; n2.next=n1; n1=n2; n2=n3; } n3=n1; n2=head; boolean res = true; while(n1 !=null && n2 !=null){ if(n1.value != n2.value){ res = false; break; } n1 =n1.next; n2=n2.next; } n1 = n3.next; n3.next = null; while(n1 != null){ n2 = n1.next; n1.next = n3; n3=n1; n1=n2; } return res; } }