详解单链表经典OJ题
文章目錄
- 前言
- 一 刪除鏈表中等于給定值“val”的所有節(jié)點(diǎn)
- 二 反轉(zhuǎn)一個(gè)單鏈表
- 三 求中間節(jié)點(diǎn)
- 四 鏈表倒數(shù)第K個(gè)節(jié)點(diǎn)
- 五 合并有序鏈表
- 六 鏈表分割
- 注意細(xì)節(jié):
- 七 刪除重復(fù)結(jié)點(diǎn)
- 八 鏈表的回文結(jié)構(gòu)
- 九 相交鏈表
- 十 判斷表中是否有環(huán)
- 十一 環(huán)形鏈表II
- OJ題目網(wǎng)址
前言
本篇文章主要就是講述數(shù)據(jù)結(jié)構(gòu)中鏈表有關(guān)的一些經(jīng)典的OJ題,文末也給大家提供了OJ題的具體網(wǎng)址供大家練習(xí),通過(guò)這些OJ題希望對(duì)你理解鏈表有一個(gè)更深層次的理解,最后創(chuàng)作不易,希望大家能夠給予鼓勵(lì),點(diǎn)點(diǎn)贊,評(píng)論交流學(xué)習(xí)!一 刪除鏈表中等于給定值“val”的所有節(jié)點(diǎn)
例如:
輸入:head = [1,2,6,3,6], val = 6
輸出:[1,2,3]
圖解過(guò)程:
刪除之后
思路有了之后,代碼如下:
二 反轉(zhuǎn)一個(gè)單鏈表
例如:
輸入:head = [1,2,3,4,5]
輸出:[5,4,3,2,1]
代碼具體實(shí)現(xiàn)
三 求中間節(jié)點(diǎn)
給定一個(gè)帶有頭結(jié)點(diǎn) head 的非空單鏈表,返回鏈表的中間結(jié)點(diǎn)。如果有兩個(gè)中間結(jié)點(diǎn),則返回第二個(gè)中間結(jié)點(diǎn)。
例如:
head=[1,2,3,4,5] 返回3
head=[1,2,3,4] 返回3
圖解分析
代碼實(shí)現(xiàn):
對(duì)于兩個(gè)節(jié)點(diǎn)的分析方法可以自己畫圖體會(huì),就能更好的理解這個(gè)題目。在這里我們提出一個(gè)變式,如果有兩個(gè)節(jié)點(diǎn),我們要求要返回第一個(gè)節(jié)點(diǎn)該怎么做?
具體的代碼實(shí)現(xiàn)如下:
四 鏈表倒數(shù)第K個(gè)節(jié)點(diǎn)
具體代碼實(shí)現(xiàn):
五 合并有序鏈表
將兩個(gè)有序鏈表合并為一個(gè)新的有序鏈表并返回。新鏈表是通過(guò)拼接給定的兩個(gè)鏈表的所有節(jié)點(diǎn)組成的。
對(duì)于這種題目我們可以采用,創(chuàng)建一個(gè)新的節(jié)點(diǎn),然后把他們都給串起來(lái)具體實(shí)現(xiàn)代碼如下:
六 鏈表分割
問題描述:
現(xiàn)有一鏈表的頭指針 ListNode head,給一定值x,編寫一段代碼將所有小于x的結(jié)點(diǎn)排在其余結(jié)點(diǎn)之前,且不能改變?cè)瓉?lái)的數(shù)據(jù)順序,返回重新排列后的鏈表的頭指針。
鏈表分割前:
分割之后:
在這里要注意的是,我們還得要先定義一個(gè)cur去遍歷鏈表,然后再利用這四個(gè)空結(jié)點(diǎn)將他們串起來(lái)。這里要值得注意的是對(duì)于一開始進(jìn)入的as,ae,bs,be,我們需要分開討論。
注意細(xì)節(jié):
1 如果x的值取的合適,對(duì)于分割的鏈表前半部分可能是沒有數(shù)據(jù)的,也就是說(shuō)as=null,那么此時(shí)我們就必須返回bs(如果后半部分也為空,那就說(shuō)明就是一個(gè)空鏈表)
2 判斷完上一個(gè)之后,我們必須要讓ae.next=bs,這樣才能把分割的鏈表鏈接起來(lái)
3 對(duì)于分割鏈表,我們不可能確保最后一個(gè)元素一定是在第二部分,也有可能是在第一部分,那么這個(gè)時(shí)候就會(huì)有一個(gè)問題,那就是這個(gè)鏈表沒有尾巴了,所以我們要把be.next置為null
具體代碼實(shí)現(xiàn):
七 刪除重復(fù)結(jié)點(diǎn)
問題描述:
在一個(gè)排序的鏈表中,存在重復(fù)的結(jié)點(diǎn),請(qǐng)刪除該鏈表中重復(fù)的結(jié)點(diǎn),重復(fù)的結(jié)點(diǎn)不保留,返回鏈表頭指針。 例如,鏈表 1->2->3->3->4->4->5 處理后為 1->2->5
刪除前:
刪除后:
通過(guò)以上兩張圖片,我們可以利用一個(gè)傀儡結(jié)點(diǎn),去把那些不重復(fù)的節(jié)點(diǎn)給串起來(lái),然后返回new.next就會(huì)是我們要得到的鏈表。
注意細(xì)節(jié):
1 不能一眼認(rèn)定,newhead.next就是head,這是不對(duì)的,因?yàn)槿绻粋€(gè)鏈表為{1,1,2,3},就可以說(shuō)明這個(gè)錯(cuò)誤的觀點(diǎn)
2 對(duì)于傀儡結(jié)點(diǎn)與鏈表直接的聯(lián)系,我們可以通過(guò)定義一個(gè)temp,讓temp=newhead,當(dāng)cur.val!=cur.next.val的時(shí)候,讓temp.next=cur
具體代碼實(shí)現(xiàn)如下:
這里要特別提一下最后的if語(yǔ)句,在這個(gè)代碼中,如果鏈表為{1,2,3,3,3},如果沒有if語(yǔ)句那么最后重復(fù)的節(jié)點(diǎn)是刪不去的,根據(jù)上面代碼,我們要得到的就是當(dāng)cur=null的時(shí)候,temp.next=null,所以在這里我們有必要在這里進(jìn)行一個(gè)這樣的判斷。
八 鏈表的回文結(jié)構(gòu)
對(duì)于一個(gè)鏈表,請(qǐng)?jiān)O(shè)計(jì)一個(gè)時(shí)間復(fù)雜度為O(n),額外空間復(fù)雜度為O(1)的算法,判斷其是否為回文結(jié)構(gòu)。給定一個(gè)鏈表的頭指針A,請(qǐng)返回一個(gè)bool值,代表其是否為回文結(jié)構(gòu)
例如:1->2->2->1
返回:true
一 需要利用快慢指針找到中點(diǎn)
二 反轉(zhuǎn)鏈表
在反轉(zhuǎn)鏈表中,我們需要定義一個(gè)cur,讓cur.next=slow,這樣就完成了當(dāng)前slow所在的下一個(gè)節(jié)點(diǎn)的反轉(zhuǎn),我們還需要往下走,需要在定義一個(gè)curNext去記錄cur的下一個(gè)節(jié)點(diǎn),不然后一個(gè)節(jié)點(diǎn)就找不到了,我們?cè)诎裺low=cur,這樣就把slow往后移了一位,我們?cè)诹頲ur=curNext,curNext=curNext.next(這里的要注意要利用一個(gè)if語(yǔ)句判斷一下,curNext是否為null),結(jié)合上述,最終的目的就是反轉(zhuǎn)到最后一個(gè)節(jié)點(diǎn)(就是slow的位置要在最后一個(gè)節(jié)點(diǎn)上),那么我們反轉(zhuǎn)節(jié)點(diǎn)肯定不止一個(gè),所以我們是需要一個(gè)循環(huán)的,那么這個(gè)循環(huán)的終止條件就是cur!=null
三 判斷回文結(jié)構(gòu)
從反轉(zhuǎn)之后的圖片來(lái)看,如果是回文結(jié)構(gòu),那么此時(shí)我們slow與head同時(shí)往后走,那么就會(huì)有head與slow相遇。這里就要特別說(shuō)一下,以上情況是針對(duì)奇數(shù)個(gè)節(jié)點(diǎn)展開的討論,偶數(shù)節(jié)點(diǎn)其實(shí)也是一樣的,只不過(guò)在判斷時(shí),變成head.next=slow,具體的圖可以自己嘗試去畫一畫。在代碼中,我會(huì)把兩種情況的總代碼寫出來(lái)。
代碼展示
九 相交鏈表
題目描述
給你兩個(gè)單鏈表的頭節(jié)點(diǎn) headA 和 headB ,請(qǐng)你找出并返回兩個(gè)單鏈表相交的起始節(jié)點(diǎn)。如果兩個(gè)鏈表不存在相交節(jié)點(diǎn),返回 null 。
對(duì)于相交節(jié)點(diǎn),我們同樣采用快慢指針的做法,設(shè)headA=slow,headB=fast,從圖中我們可以看出B比A長(zhǎng),那么我們就要定義一個(gè)整形,來(lái)表示B與A之間的長(zhǎng)度之差,讓fast多走這個(gè)差步,之后fast與slow一起走,之后就會(huì)相遇,我們就返回相遇的節(jié)點(diǎn)
對(duì)于所給的鏈表,也可以是這種,那么這個(gè)時(shí)候也不要緊,我們可以利用一個(gè)if在前一個(gè)的基礎(chǔ)上來(lái)判斷一下,如果B更長(zhǎng),我們就可以交換一下fast與slow的指向
具體實(shí)現(xiàn)代碼如下:
十 判斷表中是否有環(huán)
對(duì)于是否成環(huán)問題,我們采用快慢指針前去解決,我們讓fast一次走兩步,slow一次走一步,那么slow與fast終究會(huì)相遇的,可不敢讓fast走三次,如果只有兩個(gè)節(jié)點(diǎn),那么是永遠(yuǎn)不會(huì)相遇的
具體代碼實(shí)現(xiàn)如下
十一 環(huán)形鏈表II
給定一個(gè)鏈表,返回鏈表開始入環(huán)的第一個(gè)節(jié)點(diǎn)。 如果鏈表無(wú)環(huán),則返回 null。
如圖我們就是要返回2這個(gè)節(jié)點(diǎn),對(duì)于這種題,我們也是利用快慢指針前去解決
1 先找到fast與slow的相遇點(diǎn)
2 令fast與slow其中一個(gè)置為頭結(jié)點(diǎn)的位置,兩個(gè)一起走,就會(huì)走到入環(huán)的第一個(gè)節(jié)點(diǎn)
代碼實(shí)現(xiàn):
OJ題目網(wǎng)址
1 刪除鏈表中等于給定值 val 的所有節(jié)點(diǎn)
2 反轉(zhuǎn)一個(gè)單鏈表
3 給定一個(gè)帶有頭結(jié)點(diǎn) head 的非空單鏈表,返回鏈表的中間結(jié)點(diǎn)。如果有兩個(gè)中間結(jié)點(diǎn),則返回第二個(gè)中間結(jié)點(diǎn)。
4 輸入一個(gè)鏈表,輸出該鏈表中倒數(shù)第k個(gè)結(jié)點(diǎn)。
5 將兩個(gè)有序鏈表合并為一個(gè)新的有序鏈表并返回。新鏈表是通過(guò)拼接給定的兩個(gè)鏈表的所有節(jié)點(diǎn)組成的。
6 編寫代碼,以給定值x為基準(zhǔn)將鏈表分割成兩部分,所有小于x的結(jié)點(diǎn)排在大于或等于x的結(jié)點(diǎn)之前
7 在一個(gè)排序的鏈表中,存在重復(fù)的結(jié)點(diǎn),請(qǐng)刪除該鏈表中重復(fù)的結(jié)點(diǎn),重復(fù)的結(jié)點(diǎn)不保留,返回鏈表頭指針。
8 鏈表的回文結(jié)構(gòu)
9 輸入兩個(gè)鏈表,找出它們的第一個(gè)公共結(jié)點(diǎn)。
10 給定一個(gè)鏈表,判斷鏈表中是否有環(huán)
11 給定一個(gè)鏈表,返回鏈表開始入環(huán)的第一個(gè)節(jié)點(diǎn)。 如果鏈表無(wú)環(huán),則返回 null
總結(jié)
以上是生活随笔為你收集整理的详解单链表经典OJ题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java面向对象——包+继承+多态(一)
- 下一篇: 面向对象——多态,抽象类,接口(二)