一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

快慢指針、左右指針的常見算法

算法與數(shù)據(jù)結(jié)構(gòu) ? 來源:labuladong ? 作者:labuladong ? 2020-11-26 14:09 ? 次閱讀

作者:labuladong

公眾號(hào):labuladong

本文是一兩年前發(fā)過的一篇文章,當(dāng)時(shí)沒多少人看,現(xiàn)在由于賬號(hào)遷移的原因公眾號(hào)里都搜索不到了,我就重新加工了一下,并且添加了新內(nèi)容,直接套雙指針技巧秒殺 5 道算法題。

其實(shí),鼎鼎有名的「滑動(dòng)窗口算法」就是一種雙指針技巧,我們之前的爆文我寫了套框架,把滑動(dòng)窗口算法變成了默寫題就有這么一段:

我把雙指針技巧再分為兩類,一類是「快慢指針」,一類是「左右指針」。前者解決主要解決鏈表中的問題,比如典型的判定鏈表中是否包含環(huán);后者主要解決數(shù)組(或者字符串)中的問題,比如二分查找。

一、快慢指針的常見算法

快慢指針一般都初始化指向鏈表的頭結(jié)點(diǎn)head,前進(jìn)時(shí)快指針fast在前,慢指針slow在后,巧妙解決一些鏈表中的問題。

1、判定鏈表中是否含有環(huán)

這屬于鏈表最基本的操作了,學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)應(yīng)該對(duì)這個(gè)算法思想都不陌生。

單鏈表的特點(diǎn)是每個(gè)節(jié)點(diǎn)只知道下一個(gè)節(jié)點(diǎn),所以一個(gè)指針的話無法判斷鏈表中是否含有環(huán)的。

如果鏈表中不含環(huán),那么這個(gè)指針最終會(huì)遇到空指針null表示鏈表到頭了,這還好說,可以判斷該鏈表不含環(huán):

booleanhasCycle(ListNodehead){ while(head!=null) head=head.next; returnfalse; }

但是如果鏈表中含有環(huán),那么這個(gè)指針就會(huì)陷入死循環(huán),因?yàn)?a target="_blank">環(huán)形數(shù)組中沒有null指針作為尾部節(jié)點(diǎn)。

經(jīng)典解法就是用兩個(gè)指針,一個(gè)跑得快,一個(gè)跑得慢。如果不含有環(huán),跑得快的那個(gè)指針最終會(huì)遇到null,說明鏈表不含環(huán);如果含有環(huán),快指針最終會(huì)超慢指針一圈,和慢指針相遇,說明鏈表含有環(huán)。

力扣第 141 題就是這個(gè)問題,解法代碼如下:

booleanhasCycle(ListNodehead){ ListNodefast,slow; fast=slow=head; while(fast!=null&&fast.next!=null){ fast=fast.next.next; slow=slow.next; if(fast==slow)returntrue; } returnfalse; }

2、已知鏈表中含有環(huán),返回這個(gè)環(huán)的起始位置

這個(gè)問題一點(diǎn)都不困難,有點(diǎn)類似腦筋急轉(zhuǎn)彎,先直接看代碼:

ListNodedetectCycle(ListNodehead){ ListNodefast,slow; fast=slow=head; while(fast!=null&&fast.next!=null){ fast=fast.next.next; slow=slow.next; if(fast==slow)break; } //上面的代碼類似hasCycle函數(shù) slow=head; while(slow!=fast){ fast=fast.next; slow=slow.next; } returnslow; }

可以看到,當(dāng)快慢指針相遇時(shí),讓其中任一個(gè)指針指向頭節(jié)點(diǎn),然后讓它倆以相同速度前進(jìn),再次相遇時(shí)所在的節(jié)點(diǎn)位置就是環(huán)開始的位置。這是為什么呢?

第一次相遇時(shí),假設(shè)慢指針slow走了k步,那么快指針fast一定走了2k步:

fast一定比slow多走了k步,這多走的k步其實(shí)就是fast指針在環(huán)里轉(zhuǎn)圈圈,所以k的值就是環(huán)長(zhǎng)度的「整數(shù)倍」。

說句題外話,之前還有讀者爭(zhēng)論為什么是環(huán)長(zhǎng)度整數(shù)倍,我舉個(gè)簡(jiǎn)單的例子你就明白了,我們想一想極端情況,假設(shè)環(huán)長(zhǎng)度就是 1,如下圖:

那么fast肯定早早就進(jìn)環(huán)里轉(zhuǎn)圈圈了,而且肯定會(huì)轉(zhuǎn)好多圈,這不就是環(huán)長(zhǎng)度的整數(shù)倍嘛。

言歸正傳,設(shè)相遇點(diǎn)距環(huán)的起點(diǎn)的距離為m,那么環(huán)的起點(diǎn)距頭結(jié)點(diǎn)head的距離為k - m,也就是說如果從head前進(jìn)k - m步就能到達(dá)環(huán)起點(diǎn)。

巧的是,如果從相遇點(diǎn)繼續(xù)前進(jìn)k - m步,也恰好到達(dá)環(huán)起點(diǎn)。你甭管fast在環(huán)里到底轉(zhuǎn)了幾圈,反正走k步可以到相遇點(diǎn),那走k - m步一定就是走到環(huán)起點(diǎn)了:

所以,只要我們把快慢指針中的任一個(gè)重新指向head,然后兩個(gè)指針同速前進(jìn),k - m步后就會(huì)相遇,相遇之處就是環(huán)的起點(diǎn)了。

3、尋找鏈表的中點(diǎn)

類似上面的思路,我們還可以讓快指針一次前進(jìn)兩步,慢指針一次前進(jìn)一步,當(dāng)快指針到達(dá)鏈表盡頭時(shí),慢指針就處于鏈表的中間位置。

力扣第 876 題就是找鏈表中點(diǎn)的題目,解法代碼如下:

ListNodemiddleNode(ListNodehead){ ListNodefast,slow; fast=slow=head; while(fast!=null&&fast.next!=null){ fast=fast.next.next; slow=slow.next; } //slow就在中間位置 returnslow; }

當(dāng)鏈表的長(zhǎng)度是奇數(shù)時(shí),slow恰巧停在中點(diǎn)位置;如果長(zhǎng)度是偶數(shù),slow最終的位置是中間偏右:

尋找鏈表中點(diǎn)的一個(gè)重要作用是對(duì)鏈表進(jìn)行歸并排序。

回想數(shù)組的歸并排序:求中點(diǎn)索引遞歸地把數(shù)組二分,最后合并兩個(gè)有序數(shù)組。對(duì)于鏈表,合并兩個(gè)有序鏈表是很簡(jiǎn)單的,難點(diǎn)就在于二分。

但是現(xiàn)在你學(xué)會(huì)了找到鏈表的中點(diǎn),就能實(shí)現(xiàn)鏈表的二分了。關(guān)于歸并排序的具體內(nèi)容本文就不具體展開了。

4、尋找鏈表的倒數(shù)第n個(gè)元素

這是力扣第 19 題「刪除鏈表的倒數(shù)第n個(gè)元素」,先看下題目:

我們的思路還是使用快慢指針,讓快指針先走n步,然后快慢指針開始同速前進(jìn)。這樣當(dāng)快指針走到鏈表末尾null時(shí),慢指針?biāo)诘奈恢镁褪堑箶?shù)第n個(gè)鏈表節(jié)點(diǎn)(n不會(huì)超過鏈表長(zhǎng)度)。

解法比較簡(jiǎn)單,直接看代碼吧:

ListNoderemoveNthFromEnd(ListNodehead,intn){ ListNodefast,slow; fast=slow=head; //快指針先前進(jìn)n步 while(n-->0){ fast=fast.next; } if(fast==null){ //如果此時(shí)快指針走到頭了, //說明倒數(shù)第n個(gè)節(jié)點(diǎn)就是第一個(gè)節(jié)點(diǎn) returnhead.next; } //讓慢指針和快指針同步向前 while(fast!=null&&fast.next!=null){ fast=fast.next; slow=slow.next; } //slow.next就是倒數(shù)第n個(gè)節(jié)點(diǎn),刪除它 slow.next=slow.next.next; returnhead; }

二、左右指針的常用算法

左右指針在數(shù)組中實(shí)際是指兩個(gè)索引值,一般初始化為left = 0, right = nums.length - 1。

1、二分查找

前文二分查找框架詳解有詳細(xì)講解,這里只寫最簡(jiǎn)單的二分算法,旨在突出它的雙指針特性:

intbinarySearch(int[]nums,inttarget){ intleft=0; intright=nums.length-1; while(left<=?right)?{ ????????int?mid?=?(right?+?left)?/?2; ????????if(nums[mid]?==?target) ????????????return?mid;? ????????else?if?(nums[mid]?target) right=mid-1; } return-1; }

2、兩數(shù)之和

直接看力扣第 167 題「兩數(shù)之和 II」吧:

只要數(shù)組有序,就應(yīng)該想到雙指針技巧。這道題的解法有點(diǎn)類似二分查找,通過調(diào)節(jié)left和right可以調(diào)整sum的大?。?/p>

int[]twoSum(int[]nums,inttarget){ intleft=0,right=nums.length-1; while(lefttarget){ right--;//讓sum小一點(diǎn) } } returnnewint[]{-1,-1}; }

3、反轉(zhuǎn)數(shù)組

一般編程語(yǔ)言都會(huì)提供reverse函數(shù),其實(shí)非常簡(jiǎn)單,力扣第 344 題是類似的需求,讓你反轉(zhuǎn)一個(gè)char[]類型的字符數(shù)組,我們直接看代碼吧:

voidreverseString(char[]arr){ intleft=0; intright=arr.length-1; while(left

4、滑動(dòng)窗口算法

這也許是雙指針技巧的最高境界了,如果掌握了此算法,可以解決一大類子字符串匹配的問題,不過「滑動(dòng)窗口」稍微比上述的這些算法復(fù)雜些。

不過這類算法是有框架模板的,而且前文我寫了首詩(shī),把滑動(dòng)窗口算法變成了默寫題就講解了「滑動(dòng)窗口」算法模板,幫大家秒殺幾道子串匹配的問題,如果沒有看過,建議去看看。

責(zé)任編輯:PSY

原文標(biāo)題:雙指針技巧直接秒殺五道算法題

文章出處:【微信公眾號(hào):算法與數(shù)據(jù)結(jié)構(gòu)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 算法
    +關(guān)注

    關(guān)注

    23

    文章

    4682

    瀏覽量

    94373
  • 指針
    +關(guān)注

    關(guān)注

    1

    文章

    484

    瀏覽量

    70913
  • 滑動(dòng)窗口法
    +關(guān)注

    關(guān)注

    0

    文章

    5

    瀏覽量

    2192

原文標(biāo)題:雙指針技巧直接秒殺五道算法題

文章出處:【微信號(hào):TheAlgorithm,微信公眾號(hào):算法與數(shù)據(jù)結(jié)構(gòu)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    過程間指針分析算法的改進(jìn)

    指針分析對(duì)于使用C語(yǔ)言編制程序的數(shù)據(jù)流分析有著重要的意義。該文介紹指針問題的復(fù)雜度、指針分析算法的分類以及指針分析
    發(fā)表于 04-02 09:05 ?9次下載

    C語(yǔ)言入門教程-指針常見錯(cuò)誤

    指針常見錯(cuò)誤 錯(cuò)誤 1:未初始化的指針一個(gè)最易犯的指針錯(cuò)誤是試圖引用未初始化(因而指向的是無效地址)的指針。例如: int*p; *
    發(fā)表于 07-29 11:47 ?1200次閱讀

    C和指針習(xí)題答案配C和指針

    C和指針習(xí)題答案配C和指針
    發(fā)表于 09-07 14:29 ?6次下載
    C和<b class='flag-5'>指針</b>習(xí)題答案配C和<b class='flag-5'>指針</b>

    c語(yǔ)言函數(shù)指針定義,指針函數(shù)和函數(shù)指針的區(qū)別

     往往,我們一提到指針函數(shù)和函數(shù)指針的時(shí)候,就有很多人弄不懂。下面就由小編詳細(xì)為大家介紹C語(yǔ)言中函數(shù)指針,指針函數(shù)和函數(shù)指針之間的區(qū)別。
    發(fā)表于 11-16 15:18 ?3828次閱讀

    為什么使用指針?C++中的“指針

    為什么使用指針?因?yàn)樵诓僮鞔笮蛿?shù)據(jù)和類時(shí),指針可以通過內(nèi)存地址直接訪問數(shù)據(jù),可避免在程序中復(fù)制大量的代碼,因此指針的效率最高。一般來說,指針會(huì)有3大用途
    的頭像 發(fā)表于 10-04 10:33 ?5326次閱讀

    電機(jī)電流表指針左右擺動(dòng)的原因分析

    電機(jī)電流表指針左右擺動(dòng)是什么原因?這個(gè)問題很簡(jiǎn)單,就是電動(dòng)機(jī)帶動(dòng)的設(shè)備,有些部位不圓滑,導(dǎo)致電機(jī)帶動(dòng)時(shí)受阻,需要電流時(shí)高時(shí)低,不能同步工作,促使電流表指針來回?cái)[動(dòng),必須重新校驗(yàn)被帶負(fù)荷,使之靈活運(yùn)行,才能排除故障,恢復(fù)正常。主要
    的頭像 發(fā)表于 10-27 09:41 ?2.3w次閱讀

    理解函數(shù)指針、函數(shù)指針數(shù)組、函數(shù)指針數(shù)組的指針

    理解函數(shù)指針、函數(shù)指針數(shù)組、函數(shù)指針數(shù)組的指針
    的頭像 發(fā)表于 06-29 15:38 ?1.5w次閱讀
    理解函數(shù)<b class='flag-5'>指針</b>、函數(shù)<b class='flag-5'>指針</b>數(shù)組、函數(shù)<b class='flag-5'>指針</b>數(shù)組的<b class='flag-5'>指針</b>

    數(shù)組相關(guān)的雙指針算法

    對(duì)于單鏈表來說,大部分技巧都屬于快慢指針,前文 單鏈表的六大解題套路 都涵蓋了,比如鏈表環(huán)判斷,倒數(shù)第K個(gè)鏈表節(jié)點(diǎn)等問題,它們都是通過一個(gè)fast快指針和一個(gè)slow慢指針配合完成任務(wù)
    的頭像 發(fā)表于 04-28 16:22 ?1986次閱讀

    二級(jí)指針和多級(jí)指針的定義形式

    指針變量作為一個(gè)變量也有自己的存儲(chǔ)地址,而指向指針變量的存儲(chǔ)地址就被稱為指針指針,即二級(jí)指針
    的頭像 發(fā)表于 10-18 16:38 ?2090次閱讀

    淺談指針常量和常量指針

    這節(jié)課我們來講一講指針常量和常量指針。
    的頭像 發(fā)表于 02-21 09:27 ?1234次閱讀

    快慢指針常見算法介紹

    這應(yīng)該屬于鏈表最基本的操作了,如果讀者已經(jīng)知道這個(gè)技巧,可以跳過。 單鏈表的特點(diǎn)是每個(gè)節(jié)點(diǎn)只知道下一個(gè)節(jié)點(diǎn),所以一個(gè)指針的話無法判斷鏈表中是否含有環(huán)的。
    的頭像 發(fā)表于 04-19 10:57 ?2050次閱讀
    <b class='flag-5'>快慢</b><b class='flag-5'>指針</b>的<b class='flag-5'>常見</b><b class='flag-5'>算法</b>介紹

    指針是什么

    指針是什么? 1.1 淺談指針 理解指針的 兩個(gè)要點(diǎn): 指針是內(nèi)存中一個(gè)最小單元的編號(hào),也就是地址; 平時(shí)口語(yǔ)中說的指針,通常指的是
    的頭像 發(fā)表于 11-24 15:50 ?2590次閱讀
    <b class='flag-5'>指針</b>是什么

    函數(shù)指針指針函數(shù)是不是一個(gè)東西?

    函數(shù)指針的本質(zhì)是指針,就跟整型指針、字符指針一樣,函數(shù)指針指向的是一個(gè)函數(shù)。
    的頭像 發(fā)表于 01-03 16:35 ?659次閱讀
    函數(shù)<b class='flag-5'>指針</b>和<b class='flag-5'>指針</b>函數(shù)是不是一個(gè)東西?

    怎么理解指針指針?

    怎么理解指針指針?其實(shí)這個(gè)概念并不難,只是把它放到實(shí)際應(yīng)用中,容易造成困擾。
    的頭像 發(fā)表于 02-23 16:46 ?1497次閱讀
    怎么理解<b class='flag-5'>指針</b>的<b class='flag-5'>指針</b>?

    面試???1:函數(shù)指針指針函數(shù)、數(shù)組指針指針數(shù)組

    在嵌入式開發(fā)領(lǐng)域,函數(shù)指針、指針函數(shù)、數(shù)組指針指針數(shù)組是一些非常重要但又容易混淆的概念。理解它們的特性和應(yīng)用場(chǎng)景,對(duì)于提升嵌入式程序的效率和質(zhì)量至關(guān)重要。一、
    的頭像 發(fā)表于 08-10 08:11 ?1222次閱讀
    面試常考+1:函數(shù)<b class='flag-5'>指針</b>與<b class='flag-5'>指針</b>函數(shù)、數(shù)組<b class='flag-5'>指針</b>與<b class='flag-5'>指針</b>數(shù)組