题目及案例
package pid234;
/*回文链表
请判断一个链表是否为回文链表。
示例 1:
输入: 1->2
输出: false
示例 2:
输入: 1->2->2->1
输出: true
进阶:
你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?
*/
import pid234.LinkList;
import pid234.LinkList.ListNode;
public class main {
public static void main(String[] args) {
LinkList a=new LinkList(1);
a.addLast(2);
a.addLast(5);
a.printList();
test(a.first);
LinkList b=new LinkList(-5);
b.addLast(0);
b.addLast(-5);
b.printList();
test(b.first);
LinkList c=new LinkList(1);
c.addLast(2);
c.addLast(2);
c.addLast(1);
c.printList();
test(c.first);
/*LinkList c=new LinkList(1);
c.addLast(2);
c.addLast(500);
LinkList d=new LinkList(1);
d.addLast(2);
d.addLast(3);
c.printList();
d.printList();
test(c.first,d.first);*/
}
private static void test(ListNode ito) {
Solution solution = new Solution();
Boolean rtn;
long begin = System.currentTimeMillis();
System.out.println();
//开始时打印数组
rtn=solution.isPalindrome(ito);//执行程序
long end = System.currentTimeMillis();
System.out.println(rtn);
//System.out.println(":rtn" );
//System.out.print(rtn);
System.out.println();
System.out.println("耗时:" + (end - begin) + "ms");
System.out.println("-------------------");
}
}
linkedlist
package pid234;
public class LinkList {
public class ListNode {
public int val;
public ListNode next;
ListNode(int x)
{ val = x;
next=null;
}
public ListNode() {
val=0;
next=null;
}
public void printNodeToEnd(){
ListNode a=this;
System.out.println("print node to end");
while(a!=null){//直到最后一个不为空的节点
System.out.print(a.val+" ");
a=a.next;
}
System.out.println();
}
}
ListNode first;
public LinkList(int x){
first=new ListNode(x);
first.next=null;
}
public LinkList(){
first=null;
first.next=null;
}
public void addLast(int x){
if(first==null){
first=new ListNode(x);
return;
}
ListNode a=first;
while(a.next!=null){
a=a.next;
}
ListNode b=new ListNode(x);
a.next=b;
}
public void printList(){
ListNode a=first;
System.out.println("print listnode");
while(a!=null){//直到最后一个不为空的节点
System.out.print(a.val+" ");
a=a.next;
}
System.out.println();
}
}
解法1(成功,速度快,3ms)
速度o(n) 空间o(n)
将链表扫描加入arraylist,在头尾比较
package pid234;
import java.util.ArrayList;
import java.util.List;
import pid234.LinkList;
import pid234.LinkList.*;
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public boolean isPalindrome(ListNode head) {
List<ListNode> a=new ArrayList<ListNode>();
if(head==null){
return true;
}
ListNode x=head;
while(x!=null){
a.add(x);
x=x.next;
}
int length=a.size();
if(length==1){
return true;
}
int i=0;
while(i<length/2+1){
if(a.get(i).val!=a.get(length-i-1).val){
return false;
}
i++;
}
return true;
}
}
解法2(成功,2ms,极快)
速度o(n) 空间o(1)
先扫描得到长度,再将前一半反转
再比较两条链表
public boolean isPalindrome(ListNode head) {
if(head==null||head.next==null){
return true;
}
//先计算出有几个节点
int length=0;
ListNode now=head;
while(now!=null){
now=now.next;
length++;
}
//再将中间前一半的节点反转
int midLength=length/2;
ListNode pre=head;
ListNode next=head.next;
now=head.next;
for(int i=1;i<midLength;i++){
next=now.next;
now.next=pre;
pre=now;
now=next;
}
//双指针检查是否回文
ListNode l1;
if(midLength==1){
l1=head;
}
else{
l1=pre;
}
ListNode l2;
if(length%2==0){
l2=next;
}
else{
l2=next.next;
}
while(l2!=null){
if(l1.val==l2.val){
l1=l1.next;
l2=l2.next;
}
else{
return false;
}
}
return true;
}
解法3(别人的)
在循环的时候,使用快慢指针得到中点,而且慢指针同时将链表反转。最后比较两个链表
public boolean isPalindrome(ListNode head) {
if(head == null || head.next == null) return true;
ListNode slow = head, fast = head.next, pre = null, prepre = null;
while(fast != null && fast.next != null) {
//反转前半段链表
pre = slow;
slow = slow.next;
fast = fast.next.next;
//先移动指针再来反转
pre.next = prepre;
prepre = pre;
}
ListNode p2 = slow.next;
slow.next = pre;
ListNode p1 = fast == null? slow.next : slow;
while(p1 != null) {
if(p1.val != p2.val)
return false;
p1 = p1.next;
p2 = p2.next;
}
return true;
}