請判斷乙個鍊錶是否為回文鍊錶。示例 1:
輸入:1-
>
2輸出:
false
示例 2:
輸入:1-
>2-
>2-
>
1輸出:
true
解法一:可以使用棧先進後出的特點進行解題,遍歷鍊錶將所有元素進行壓棧,然後再從頭遍歷一次鍊錶,與棧彈出的節點進行對比,看是否相等。需要注意的是比較的是節點的value值是否相等,而不是比較兩個節點是否相等。
解法二:
解法一的空間複雜度為o(n),為了使空間複雜度為o(1),可以使用快慢指標拆分鍊錶為兩段然後進行比較。參考文章:leetcode官方題解
我們可以將鍊錶的後半部分反轉(修改鍊錶結構),然後將前半部分和後半部分進行比較。比較完成後我們應該將鍊錶恢復原樣。雖然不需要恢復也能通過測試用例,但是使用該函式的人通常不希望鍊錶結構被更改。演算法該方法雖然可以將空間複雜度降到
o(1),但是在併發環境下,該方法也有缺點。在併發環境下,函式執行時需要鎖定其他執行緒或程序對鍊錶的訪問,因為在函式執行過程中煉表會被修改。
整個流程可以分為以下五個步驟:
找到前半部分鍊錶的尾節點。
反轉後半部分鍊錶。
判斷是否回文。
恢復鍊錶。
返回結果。
執行步驟一,我們可以計算鍊錶節點的數量,然後遍歷鍊錶找到前半部分的尾節點。解法一:我們也可以使用快慢指標在一次遍歷中找到:慢指標一次走一步,快指標一次走兩步,快慢指標同時出發。當快指標移動到鍊錶的末尾時,慢指標恰好到鍊錶的中間。通過慢指標將鍊錶分為兩部分。
若煉表有奇數個節點,則中間的節點應該看作是前半部分。
步驟二可以使用「206. 反轉鍊錶」問題中的解決方法來反轉鍊錶的後半部分。
步驟三比較兩個部分的值,當後半部分到達末尾則比較完成,可以忽略計數情況中的中間節點。
步驟四與步驟二使用的函式相同,再反轉一次恢復鍊錶本身。
public
boolean
ispalindrome
(listnode head)
t = head;
while
(t!=null &&
!stack.
isempty()
) t = t.next;
}return
true
;}
提交結果:
解法二:
class
solution
// 找到前半部分鍊錶的尾節點並反轉後半部分鍊錶
listnode firsthalfend =
endoffirsthalf
(head)
; listnode secondhalfstart =
reverselist
(firsthalfend.next)
;// 判斷是否回文
listnode p1 = head;
listnode p2 = secondhalfstart;
boolean result =
true
;while
(result && p2 != null)
p1 = p1.next;
p2 = p2.next;
}// 還原鍊錶並返回結果
firsthalfend.next =
reverselist
(secondhalfstart)
;return result;
}private listnode reverselist
(listnode head)
return prev;
}private listnode endoffirsthalf
(listnode head)
return slow;
}}
提交結果: leetcode刷題234 回文鍊錶
題目描述 請判斷乙個鍊錶是否為回文鍊錶。示例 1 輸入 1 2 輸出 false示例 2 輸入 1 2 2 1 輸出 true高階 你能否用 o n 時間複雜度和 o 1 空間複雜度解決此題?思路 將鍊錶中的資料轉存到陣列中,在陣列中用雙指標比較 definition for singly link...
LeetCode演算法題234 回文鍊錶解析
請判斷乙個鍊錶是否為回文鍊錶。示例 1 輸入 1 2 輸出 false示例 2 輸入 1 2 2 1 輸出 true高階 你能否用 o n 時間複雜度和 o 1 空間複雜度解決此題?這個題稍微有些複雜,首先一定得找到中點,所以還是使用快慢指標,當快指標到達終點時,慢指標就到中點了,然後需要用棧來儲存...
LeetCode刷題日記 234 回文鍊錶
判斷乙個給定的鍊錶是否為回文鍊錶。我首先想到的第乙個方案是用反轉鍊錶中的步驟將整個鍊錶反轉,然後比較反轉後的鍊錶與反轉前鍊錶是否相同,如下 definition for singly linked list.struct listnode class solution if curr head el...