判斷迴文連結串列
阿新 • • 發佈:2020-11-06
問題描述
請判斷一個連結串列是否為迴文連結串列。連結串列為單向無環連結串列
示例 1:
輸入: 1->2 輸出: false
示例 2:
輸入: 1->2->2->1 輸出: true
解法一:
這題是讓判斷連結串列是否是迴文連結串列,所謂的迴文連結串列就是以連結串列中間為中心點兩邊對稱。我們常見的有判斷一個字串是否是迴文字串,這個比較簡單,可以使用兩個指標,一個最左邊一個最右邊,兩個指標同時往中間靠,判斷所指的字元是否相等。
但這題判斷的是連結串列,因為這裡是單向連結串列,只能從前往後訪問,不能從後往前訪問,所以使用判斷字串的那種方式是行不通的。但我們可以通過找到連結串列的中間節點然後把連結串列後半部分反轉,最後再用後半部分反轉的連結串列和前半部分一個個比較即可。這裡以示例2為例畫個圖看一下。
最後再來看下程式碼:
public boolean isPalindrome(ListNode head) { ListNode slow = head, fast = head; //快慢指標 while (fast != null && fast.next != null) { slow = slow.next; fast = fast.next.next; } //如果fast不為空,說明連結串列的長度是奇數個 if (fast != null) { slow=slow.next; } //反轉後半部分連結串列 slow = reverse(slow); fast=head; while (slow!=null){ //不是迴文 if (fast.val!=slow.val){ return false; } slow=slow.next; fast=fast.next; }return true; } //反轉連結串列 public ListNode reverse(ListNode head) { ListNode pre = null; while (head != null) { ListNode next = head.next; head.next = pre; pre = next; head = next; } return pre; }
解法二:
我們知道棧是先進後出的一種資料結構,這裡還可以使用棧先把連結串列的節點全部存放到棧中,然後再一個個出棧,這樣就相當於連結串列從後往前訪問了,通過這種方式也能解決,看下程式碼:
public boolean isPalindrome1(ListNode head) { if (head == null) { return true; } ListNode temp = head; Stack<Integer> stack = new Stack(); int len = 0; while (temp != null) { stack.push(temp.val); temp = temp.next; len++; } //長度除以2 len >>= 1; while (len-- > 0) { if (head.val != stack.pop()) { return false; } head = head.next; } return true; }
解法三(遞迴):
ListNode temp; public boolean isPalindrome2(ListNode head) { temp = head; return check(temp); } private boolean check(ListNode head) { if (head == null){ return true; } //逆序列印連結串列 boolean res = check(head.next) && (temp.val == head.val); temp = temp.next; return res; }
總結:
迴文連結串列的判斷,相比迴文字串的判斷稍微要麻煩一點,但難度也不是很大,如果對連結串列比較熟悉的話,這3種解決方式都很容易想到,如果不熟悉的話,可能最容易想到的就是第2種了,也就是棧和連結串列的結合。