1. 程式人生 > >LeetCode234_PalindromeLinkedList (判斷是否為迴文連結串列) Java題解

LeetCode234_PalindromeLinkedList (判斷是否為迴文連結串列) Java題解

題目:

Given a singly linked list, determine if it is a palindrome.

Follow up:
Could you do it in O(n) time and O(1) space?

題解:

判斷一個連結串列是不是迴文的,這裡要求O(n)時間複雜度和O(1)的空間時間複雜度,總共想了三種辦法,三種辦法都用到了兩個指標,符合題目要求的只有最後一種。

第一種辦法:用陣列倒著存前半段的連結串列的值,然後和後半段連結串列的值進行比較。這種解法執行的時間最久可能是因為陣列倒著插入比較耗時。

程式碼:

//用陣列實現 o(n/2)空間
	 public static boolean isPalindrome(ListNode head) {
		
		// ArrayList<Integer> nodeVal=new ArrayList<>();
		 LinkedList<Integer> nodeVal=new LinkedList<>();
		 
		 if(head==null||head.next==null)
			 return true;
		 ListNode slow=head;
		 ListNode fast=head;
		 
		 nodeVal.add(0,slow.val);
		 while(fast.next!=null&&fast.next.next!=null)
		 {
			 fast=fast.next.next;
			 slow=slow.next;
			 nodeVal.add(0,slow.val);
		 }
		 
		 ListNode cur=slow;
		 if(fast.next!=null)//連結串列長度為偶數
			 cur=slow.next;
		 int i=0;
		 while(cur!=null)
		 {
			 if(nodeVal.get(i)!=cur.val)
				 return false;
			 cur=cur.next;
			 i++;
		 }
		 return true;
	    }
	 
第二種解法:在第一種的思路的基礎上,我們要實現一個倒序,我們幹嘛不用現成的資料結構-棧,於是把連結串列前半段壓棧,然後出棧和後面的連結串列依次比較,這種執行時間最短,但因為用到了棧還是不符合題目要求。

程式碼:

 //用棧實現
	 public static boolean isPalindrome2(ListNode head) {
		 
		 Stack<ListNode> stack=new Stack<>();
		 ListNode slow=head;
		 ListNode fast=head;
		 
		 if(fast==null||fast.next==null)//0個節點或是1個節點
			 return true;

		 stack.push(slow);
		 while(fast.next!=null&&fast.next.next!=null)
		 {
			
			 fast=fast.next.next;
			 slow=slow.next;
			 stack.push(slow);
		 }
		 if(fast.next!=null)//連結串列長度為偶數
			 slow=slow.next;
		 
		 ListNode cur=slow;
		 while(cur!=null)
		 {
			 if(cur.val!=stack.pop().val)
				 return false;
			 cur=cur.next;
		 }
		 return true;
	 
	 }

第三種:我們這樣想,我們可不可以不借助外在的儲存實現倒序呢,其實是可以的,連結串列反轉的時候我們就沒有藉助外在儲存。思路是把後半段的原地連結串列反轉然後和前半段進行比較(當然你也可以反轉前半段)執行時間稍微比第二種慢一些,但是符合題目O(1)空間複雜度的要求

程式碼:

	 //連結串列原地轉置實現o(1)空間複雜度
	 public static boolean isPalindrome3(ListNode head) {
		 ListNode slow=head;
		 ListNode fast=head;
		 
		 if(fast==null||fast.next==null)//0個節點或是1個節點
			 return true;


		 while(fast.next!=null&&fast.next.next!=null)
		 {
			 fast=fast.next.next;
			 slow=slow.next;
		 }
		 //對連結串列後半段進行反轉
		 ListNode midNode=slow;
		 ListNode firNode=slow.next;//後半段連結串列的第一個節點
		 ListNode cur=firNode.next;//插入節點從第一個節點後面一個開始
		 firNode.next=null;//第一個節點最後會變最後一個節點
		 while(cur!=null)
		 {
			 ListNode nextNode=cur.next;//儲存下次遍歷的節點
			 cur.next=midNode.next;
			 midNode.next=cur;
			 cur=nextNode;
		 }
		 
		 //反轉之後對前後半段進行比較
		 slow=head;
		 fast=midNode.next;
		 while(fast!=null)
		 {
			 if(fast.val!=slow.val)
				 return false;
			 slow=slow.next;
			 fast=fast.next;
		 }
		 return true;
		 
	 }