雙指針技巧還能夠分爲兩類,一類是「快慢指針」,另外一類是「左右指針」。 前者解決主要解決鏈表中的問題,好比典型的斷定鏈表中是否包含環;後者主要解決數組(或者字符串)中的問題,好比二分查找。html
環形鏈表
給定一個鏈表,判斷鏈表中是否有環。web
題目分析
-
JS特殊解法
相信對於 JS 中的 JSON.stringify() 方法你們都用過,主要用於將 JS 對象 轉換爲 JSON 字符串。基本使用以下:算法
var car = {
name: '環形鏈表',
age: 123,
}
var str = JSON.stringify(car);
console.log(str)
// {"name":"環形鏈表","age":123}
你們想一下,若是是本身實現這樣的一個函數,咱們須要處理什麼樣的特殊狀況?對,就是循環引用。由於對於循環引用,咱們很難經過 JSON 的結構將其進行展現!數組
好比下面:微信
var ls = {
name: '李四',
age: 27
}
var zs = {
name: '張三',
age: 12
}
ls.father = zs;
zs.father = ls;
console.log(zs)
console.log(JSON.stringify(zs))
因此咱們能夠經過 JSON.stringify() 的特性進行求解:編輯器
var hasCycle = function(head) {
try{
JSON.stringify(head)
}catch(e){
return true
}
return false
};
固然,這種解法並非建議的標準題解!在此列出是爲了拓寬思惟!(你們若有興趣,能夠本身去看下JSON.stringify 內部的實現,是如何檢測循環引用的。)函數
-
雙指針解法
也是本題標準解法!flex
思路來源:先想象一下,兩名運動員以不一樣速度在跑道上進行跑步會怎麼樣?spa
相遇!.net
好了,這道題你會了。
解題方法:經過使用具備 不一樣速度 的快、慢兩個指針遍歷鏈表,空間複雜度能夠被下降至 O(1)。慢指針每次移動一步,而快指針每次移動兩步。
假設鏈表爲
其步驟以下:
分析完畢,直接上代碼:
var ls = {
name: '李四',
age: 3
}
var zs = {
name: '張三',
age: 2
}
var ww = {
name: '王五',
age: 4
}
var zl = {
name: '趙六',
age: 0
}
ls.next = zs;
zs.next = ww;
ww.next = zl;
zl.next = ls;
console.log(zs);
function hasCycle(ListNode) {
if (!ListNode) return;
let fast = ListNode.next; // 快指針圖1
while (fast && ListNode && fast.next) {
if (fast == ListNode) {
return true;
}
ListNode = ListNode.next;
fast = fast.next.next
}
return false;
}
console.log(hasCycle(zs));
zl.next = {};
console.log(hasCycle(zs));
這裏咱們要特別說明一下,爲何慢指針的步長設置爲 1 ,而快指針步長設置爲 2 。
首先,慢指針步長爲 1,很容易理解,由於咱們須要讓慢指針步行至每個元素。而快指針步長爲 2 ,通俗點能夠理解爲他們的相對速度只差 1,快的只能一個一個格子的去追慢的,必然在一個格子相遇。
若是沒看懂,咱們來分析:在快的快追上慢的時,他們之間必定是隻差 1 個或者 2 個格子。若是落後 1 個,那麼下一次就追上了。若是落後 2 個,那麼下一次就落後 1 個,再下一次就能追上!
以下圖:
因此咱們的快指針的步長能夠設置爲 2 。
原文參考
-
小浩算法:https://www.geekxh.com/1.1.%E9%93%BE%E8%A1%A8%E7%B3%BB%E5%88%97/103.html
本文分享自微信公衆號 - JavaScript忍者祕籍(js-obok)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。