1. 程式人生 > >【日拱一卒】連結串列——迴文判斷

【日拱一卒】連結串列——迴文判斷

需求

判斷一個連結串列是否是迴文連結串列

迴文的形式大家應該都知道,類似

abcba
或者
abccba

這種對稱的方式都是迴文。

 

難點

如果將連結串列形式換成陣列,是不是就簡單很多了。針對一個長度為n的陣列,我們可以一一比對節點0和節點n-1,節點1和節點n-2,直到收尾索引相等。

但是這裡說的是連結串列,顯然遍歷完整個連結串列,找到尾結點,然後再回溯進行比較顯得有些不切實際,況且這裡並不是雙向連結串列。

所以這裡就要換個思路,重點是從迴文的對稱性著手。

 

思路

關鍵字:快慢指標、連結串列反轉

1、初始化兩個指標快指標和慢指標,慢指標每次走一步,快指標每次走兩步

2、依次遍歷整個連結串列,直到快指標遍歷完連結串列

此時fast指標已經率先到達連結串列的尾結點,停止遍歷。因為該連結串列包含奇數個元素,所以slow節點需要再移動一步。指向節點2。

3、此時藉助慢指標將後半部分連結串列反轉

反轉後連結串列頭指標為pre

4、依次遍歷比較原來連結串列和反轉後的連結串列pre的值是否相等,直到pre遍歷到尾結點。

有了如上思路,寫出對應程式碼就是順理成章的事了。

 

程式碼實現

func isPalindrome(head *ListNode) bool {
	if head == nil || head.Next == nil {
		return true
	}
	
	fast := head
	slow := head

	// 快慢指標,快指標每次移動兩步,慢指標每次移動一步
	for fast != nil && fast.Next != nil {
		slow = slow.Next
		fast = fast.Next.Next
	}

	//如果是奇數,則慢指標再移動一步,到達中心點
	if fast != nil {
		slow = slow.Next
	}

	// 慢指標反轉
	var pre *ListNode = nil
	for slow != nil {
		pre, slow, slow.Next =slow, slow.Next, pre
	}

	cur := head
	for cur != nil && pre != nil {
		if cur.Val == pre.Val {
			cur = cur.Next
			pre = pre.Next
		} else {
			return false
		}
	}

	return true
}

  

不忘初心

老王:你不好好種地,你以後長大能幹什麼

小王:學演算法

老王:學演算法?!你陣列、連結串列、棧、佇列、堆、排序、查詢都整不明白,你學什麼演算法

小王:我只學連結串列迴文判斷

老王:。。。

 

如果您覺得閱讀本文對您有幫助,請點一下“推薦”按鈕,您的“推薦”將是我最大的寫作動力!如果您想持續關注我的文章,請掃描二維碼,關注JackieZheng的微信公眾號,我會將我的文章推送給您,並和您一起分享我日常閱讀過的優質文章。