代碼隨想錄算法訓(xùn)練營(yíng)第三天| 203. 移除鏈表元素处渣、707. 設(shè)計(jì)鏈表伶贰、面試題、 206. 反轉(zhuǎn)鏈表

203. 移除鏈表元素

給你一個(gè)鏈表的頭節(jié)點(diǎn) head 和一個(gè)整數(shù) val 罐栈,請(qǐng)你刪除鏈表中所有滿足 Node.val == val 的節(jié)點(diǎn)黍衙,并返回 新的頭節(jié)點(diǎn) 。

解題思路

這道題的思路是找到第一個(gè)節(jié)點(diǎn)值不等于val的節(jié)點(diǎn)荠诬,然后判斷下一個(gè)節(jié)點(diǎn)的值是否不等于val琅翻,,如果不等于柑贞,則把當(dāng)前節(jié)點(diǎn)的next鏈接到下一個(gè)節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn)方椎,以此遍歷,直到next節(jié)點(diǎn)為空钧嘶,基于以上考慮棠众,我們可以構(gòu)建出一個(gè)虛擬節(jié)點(diǎn),使其指向head康辑。這樣虛擬節(jié)點(diǎn)就可以作為第一個(gè)節(jié)點(diǎn)值不為val的節(jié)點(diǎn)摄欲,完成上面所說的遍歷。

代碼

class Solution {
    public ListNode removeElements(ListNode head, int val) {
        ListNode node = new ListNode(0,head);
        ListNode temp = node;
        while(temp.next!=null){
            if(temp.next.val == val){
                temp.next = temp.next.next;
            }else{
                temp= temp.next;
            }
        }
        return node.next;
    }
}

總結(jié)

這道題如果不采用虛擬節(jié)點(diǎn)方式也可以實(shí)現(xiàn)疮薇,只是需要多一步找到第一個(gè)節(jié)點(diǎn)值不為val的節(jié)點(diǎn)胸墙,然后按照以上的判斷邏輯去循環(huán)遍歷好。
需要注意的點(diǎn):如果當(dāng)前節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn)的值等于val按咒,只需要將當(dāng)前節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn)指向下一個(gè)節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn)就好迟隅,而不用將當(dāng)前節(jié)點(diǎn)賦值到下一個(gè)節(jié)點(diǎn)。因?yàn)槲覀兪桥袛嘞乱粋€(gè)節(jié)點(diǎn)是否滿足需求励七,而賦值后智袭,下一個(gè)節(jié)點(diǎn)已經(jīng)是一個(gè)新的節(jié)點(diǎn)了,可以直接判斷

707. 設(shè)計(jì)鏈表

設(shè)計(jì)鏈表的實(shí)現(xiàn)掠抬。您可以選擇使用單鏈表或雙鏈表吼野。單鏈表中的節(jié)點(diǎn)應(yīng)該具有兩個(gè)屬性:val 和 next。val 是當(dāng)前節(jié)點(diǎn)的值两波,next 是指向下一個(gè)節(jié)點(diǎn)的指針/引用瞳步。如果要使用雙向鏈表闷哆,則還需要一個(gè)屬性 prev 以指示鏈表中的上一個(gè)節(jié)點(diǎn)。假設(shè)鏈表中的所有節(jié)點(diǎn)都是 0-index 的单起。
在鏈表類中實(shí)現(xiàn)這些功能

  • get(index):獲取鏈表中第 index 個(gè)節(jié)點(diǎn)的值抱怔。如果索引無效,則返回-1嘀倒。
  • addAtHead(val):在鏈表的第一個(gè)元素之前添加一個(gè)值為 val 的節(jié)點(diǎn)屈留。插入后,新節(jié)點(diǎn)將成為鏈表的第一個(gè)節(jié)點(diǎn)测蘑。
  • addAtTail(val):將值為 val 的節(jié)點(diǎn)追加到鏈表的最后一個(gè)元素灌危。
  • addAtIndex(index,val):在鏈表中的第 index 個(gè)節(jié)點(diǎn)之前添加值為 val 的節(jié)點(diǎn)。如果 index 等于鏈表的長(zhǎng)度帮寻,則該節(jié)點(diǎn)將附加到鏈表的末尾乍狐。如果 index 大于鏈表長(zhǎng)度赠摇,則不會(huì)插入節(jié)點(diǎn)固逗。如果index小于0,則在頭部插入節(jié)點(diǎn)藕帜。
  • deleteAtIndex(index):如果索引 index 有效烫罩,則刪除鏈表中的第 index 個(gè)節(jié)點(diǎn)。

解題思路

這道題可以覆蓋了鏈表的常用操作洽故,我們可以采取單鏈表或者雙鏈表的方式去實(shí)現(xiàn)贝攒,而不管是采用單鏈表和雙鏈表的形式,我們都需要考慮頭節(jié)點(diǎn)或頭尾節(jié)點(diǎn)對(duì)鏈表在操作中的影響(對(duì)頭節(jié)點(diǎn)或者頭尾節(jié)點(diǎn)的特殊處理)时甚,基于這一考慮隘弊,我們可以通過虛擬頭尾節(jié)點(diǎn)的方式,來消除這種影響荒适。

代碼

單鏈表
class MyLinkedList {

    private int size;
    private ListNode head;


    public MyLinkedList() {
        size = 0;
        head = new ListNode(-1);
    }
    
    public int get(int index) {
        ListNode listNode = getListNodeByIndex(index+1);
        if(listNode == null){
            return -1;
        }
        return listNode.val;
    }
    
    public void addAtHead(int val) {
        addAtIndex(0,val);
    }
    
    public void addAtTail(int val) {
        addAtIndex(size,val);
    }
    
    public void addAtIndex(int index, int val) {
        if(index>size){
            return;
        }
        if(index <0){
            index = 0;
        }
        ListNode preNode = getListNodeByIndex(index);
        ListNode nextNode = preNode.next;
        preNode.next = new ListNode(val,nextNode);
        size++;
    }
    
    public void deleteAtIndex(int index) {
        if(index<0 || index>=size){
            return;
        }
        if(index == 0){
           head = head.next;
           return;
        }
        ListNode findNode = getListNodeByIndex(index);
        ListNode nextNode = findNode.next.next;
        findNode.next = nextNode;
        size--;
    }

    /**
    獲取第index節(jié)點(diǎn)梨熙,注意:第0個(gè)節(jié)點(diǎn)為虛擬節(jié)點(diǎn),第一個(gè)節(jié)點(diǎn)才是真正的第0個(gè)節(jié)點(diǎn)
    所以index有效的最大值為size而不是size-1
     */
    private ListNode getListNodeByIndex(int index){
        if(index<0 || index>size){
            return null;
        }
        ListNode findNode = head;
        for(int i = 0;i<index;i++){
            findNode = findNode.next;
        }
        return findNode;
    }

    //定義出單鏈表節(jié)點(diǎn)類

    class ListNode{

        public int val;

        public ListNode next;

        public ListNode(){

        }

        public ListNode(int val){
            this(val,null);
        }

        public ListNode(int val,ListNode next){
            this.val = val;
            this.next = next;
        }
    }
}
雙鏈表
class MyLinkedList {

    private int size;
    private ListNode head;
    private ListNode tail;


    public MyLinkedList() {
        size = 0;
        head = new ListNode(0);
        tail = new ListNode(0);
        head.nextNode = tail;
        tail.preNode = head;
    }
    
    public int get(int index) {
        if(index<0 || index>=size){
            return -1;
        }
        ListNode findNode = getListNode(index+1);
        return findNode.val;
    }
    
    public void addAtHead(int val) {
        addAtIndex(0,val);
    }
    
    public void addAtTail(int val) {
        addAtIndex(size,val);
    }
    
    public void addAtIndex(int index, int val) {
        if(index>size){
            return;
        }
        if(index<0){
            index = 0;
        }
        ListNode preNode = getListNode(index);
        ListNode next = preNode.nextNode;
        preNode.nextNode = new ListNode(val,preNode,next);
         next.preNode = preNode.nextNode;
        size++;
    }
    
    public void deleteAtIndex(int index) {
        if(index<0||index>=size){
            return;
        }
        ListNode findNode = getListNode(index+1);
        ListNode preNode = findNode.preNode;
        ListNode nextNode = findNode.nextNode;
        preNode.nextNode = nextNode;
        nextNode.preNode = preNode;
        size--;
    }

    /**
    根據(jù)index獲取到對(duì)應(yīng)的node刀诬,注意咽扇,這里的index是包含head和tail兩個(gè)虛擬節(jié)點(diǎn)的index
     */
    private ListNode getListNode(int index){
        if(index<0||index>size+1){
            return null;
        }
        ListNode findNode;
        if(index<=size/2){
            findNode = head;
            for(int i=0;i<index;i++){
                findNode = findNode.nextNode;
            }
        }else{
            findNode = tail;
            for(int i = size+1;i>index;i--){
                findNode = findNode.preNode;
            }
        }
        return findNode;
    }

    public class ListNode{
        int val;
        ListNode preNode;
        ListNode nextNode;

        public ListNode(int val){
            this(val,null,null);
        }
        public ListNode(int val,ListNode preNode,ListNode nextNode){
            this.val = val;
            this.preNode = preNode;
            this.nextNode = nextNode;
        }

    }
}

總結(jié)

從以上的代碼可以看出來,添加虛擬節(jié)點(diǎn)可以很好的幫助我們解決收尾問題陕壹,因?yàn)椴还芪覀冊(cè)趺床僮髦视孜补?jié)點(diǎn)都不會(huì)被刪除,需要注意的是糠馆,因?yàn)槲覀兲砑恿颂摂M節(jié)點(diǎn)嘶伟,所以在獲取index節(jié)點(diǎn)的時(shí)候需要注意到底是獲取不包含虛擬節(jié)點(diǎn)的index還是獲取需要包含虛擬節(jié)點(diǎn)的index,例如雙鏈表在添加的時(shí)候又碌,我們是需要弄清我們到底是需要獲取新添加節(jié)點(diǎn)的前一個(gè)節(jié)點(diǎn)還是后一個(gè)節(jié)點(diǎn)九昧,這對(duì)我們后續(xù)處理鏈表的操作起到了關(guān)鍵的作用盛霎。

206. 反轉(zhuǎn)鏈表

給你單鏈表的頭節(jié)點(diǎn) head ,請(qǐng)你反轉(zhuǎn)鏈表耽装,并返回反轉(zhuǎn)后的鏈表愤炸。

思路

看到這道題,我們可以想到想要去反轉(zhuǎn)鏈表掉奄,那我們可以用一個(gè)節(jié)點(diǎn)記錄上一個(gè)節(jié)點(diǎn)规个,然后遍歷到當(dāng)前節(jié)點(diǎn)時(shí),把當(dāng)前節(jié)點(diǎn)的next賦值給之前記錄的上一個(gè)節(jié)點(diǎn)姓建,那么我們可以想到使用雙指針的方式去完成诞仓,兩個(gè)指針分別指向上一個(gè)節(jié)點(diǎn)和當(dāng)前節(jié)點(diǎn),然后循環(huán)去往后移動(dòng)速兔,直到當(dāng)前節(jié)點(diǎn)為null墅拭,而指向上一個(gè)節(jié)點(diǎn)的指針指向的節(jié)點(diǎn)即為新的頭節(jié)點(diǎn)

代碼

class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode pre = null;
        ListNode temp = null;
        while(head!=null){
            temp = head.next;
            head.next = pre;
            pre = head;
            head = temp;
        }
        return pre;
    }
}

總結(jié)

利用雙指針的方式可以比較容易的完成這題,我們用head來作為指向當(dāng)前節(jié)點(diǎn)的指針涣狗,pre用于指向上一個(gè)節(jié)點(diǎn)的指針谍婉,而pre的初始就是null,這樣一直遍歷下去镀钓,就可以將鏈表反轉(zhuǎn)穗熬,需要注意的是,遍歷完成后丁溅,head指針指向的為null唤蔗,而pre指針,指向的才是真正的新的鏈表的頭結(jié)點(diǎn)窟赏。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末妓柜,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子涯穷,更是在濱河造成了極大的恐慌棍掐,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件求豫,死亡現(xiàn)場(chǎng)離奇詭異塌衰,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)蝠嘉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門最疆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蚤告,你說我怎么就攤上這事努酸。” “怎么了杜恰?”我有些...
    開封第一講書人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵获诈,是天一觀的道長(zhǎng)仍源。 經(jīng)常有香客問我,道長(zhǎng)舔涎,這世上最難降的妖魔是什么笼踩? 我笑而不...
    開封第一講書人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮亡嫌,結(jié)果婚禮上嚎于,老公的妹妹穿的比我還像新娘。我一直安慰自己挟冠,他們只是感情好于购,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著知染,像睡著了一般肋僧。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上控淡,一...
    開封第一講書人閱讀 49,185評(píng)論 1 284
  • 那天嫌吠,我揣著相機(jī)與錄音,去河邊找鬼逸寓。 笑死居兆,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的竹伸。 我是一名探鬼主播,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼簇宽,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼勋篓!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起魏割,我...
    開封第一講書人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤譬嚣,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后钞它,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體拜银,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年遭垛,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了尼桶。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡锯仪,死狀恐怖泵督,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情庶喜,我是刑警寧澤小腊,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布救鲤,位于F島的核電站,受9級(jí)特大地震影響秩冈,放射性物質(zhì)發(fā)生泄漏本缠。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一入问、第九天 我趴在偏房一處隱蔽的房頂上張望搓茬。 院中可真熱鬧,春花似錦队他、人聲如沸卷仑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽锡凝。三九已至,卻和暖如春垢啼,著一層夾襖步出監(jiān)牢的瞬間窜锯,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來泰國(guó)打工芭析, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留锚扎,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓馁启,卻偏偏與公主長(zhǎng)得像驾孔,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子惯疙,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容