D3|203.移除鏈表元素、707.設計鏈表、206反轉(zhuǎn)鏈表

LeetCode 203.移除鏈表元素

題目:給你一個鏈表的頭節(jié)點?head?和一個整數(shù)val?,請你刪除鏈表中所有滿足?Node.val == val?的節(jié)點,并返回新的頭節(jié)點?。

代碼:

法一:直接對原鏈表操作。這種方法要考慮兩種情況:1、頭節(jié)點剛好是要刪除的點;2、非頭節(jié)點是要刪除的點。第一種情況通過head=head->next實現(xiàn)頭節(jié)點的移動,第二種情況就是正常的刪除節(jié)點的操作。有一種特殊情況需要考慮到:例如刪除的元素是1,但是鏈表里面全是1,這時候頭節(jié)點應該不斷地向后移動,直至為空,所以第一種情況的代碼中應該用while而不是if。此外在寫代碼時要注意,我們不能對空指針進行操作,所以在對進入循環(huán)時要判斷空節(jié)點的情況。

/**

* Definition for singly-linked list.

* struct ListNode {

*? ? int val;

*? ? ListNode *next;

*? ? ListNode() : val(0), next(nullptr) {}

*? ? ListNode(int x) : val(x), next(nullptr) {}

*? ? ListNode(int x, ListNode *next) : val(x), next(next) {}

* };

*/

class Solution {

public:

? ? ListNode* removeElements(ListNode* head, int val) {

? ? while(head!=NULL&&head->val==val)

? ? {

? ? ? ? ListNode* temp=head;

? ? ? ? head=head->next;

? ? ? ? delete temp;

? ? }

? ? ListNode* p=head;

? ? while(p!=NULL&&p->next!=NULL)

? ? {

? ? ? ? if(p->next->val==val)

? ? ? ? {

? ? ? ? ? ? ListNode* temp=p->next;

? ? ? ? ? ? p->next=temp->next;

? ? ? ? ? ? delete temp;

? ? ? ? }

? ? ? ? else{

? ? ? ? ? ? p=p->next;

? ? ? ? }

? ? }

? ? return head;

? ? }

};

法二:構造虛擬頭節(jié)點。這種方法是在頭節(jié)點之前再加上一個節(jié)點,把頭節(jié)點變成一個中間的節(jié)點,避免了法一的分類判斷,這樣代碼更加簡潔。需要注意的是,最后返回的指針是vhead->next,因為原來的head可能被刪除了,而虛擬頭節(jié)點的下一個節(jié)點永遠都是原鏈表的頭節(jié)點。

/**

* Definition for singly-linked list.

* struct ListNode {

*? ? int val;

*? ? ListNode *next;

*? ? ListNode() : val(0), next(nullptr) {}

*? ? ListNode(int x) : val(x), next(nullptr) {}

*? ? ListNode(int x, ListNode *next) : val(x), next(next) {}

* };

*/

class Solution {

public:

? ? ListNode* removeElements(ListNode* head, int val) {

? ? ListNode *vhead=new ListNode(0);

? ? vhead->next=head;

? ? ListNode *p=vhead;

? ? while(p!=NULL&&p->next!=NULL)

? ? {


? ? ? ? if(p->next->val==val)

? ? ? ? {

? ? ? ? ? ? ListNode* temp=p->next;

? ? ? ? ? ? p->next=temp->next;

? ? ? ? ? ? delete temp;

? ? ? ? }else{

? ? ? ? ? ? p=p->next;

? ? ? ? }

? ? }

? ? return vhead->next;

? ? }

};


LeetCode 707.設計鏈表

題目:設計鏈表的實現(xiàn)。您可以選擇使用單鏈表或雙鏈表。單鏈表中的節(jié)點應該具有兩個屬性:val和next。val是當前節(jié)點的值,next是指向下一個節(jié)點的指針/引用。如果要使用雙向鏈表,則還需要一個屬性prev以指示鏈表中的上一個節(jié)點。假設鏈表中的所有節(jié)點都是 0-index 的。

在鏈表類中實現(xiàn)這些功能:get(index):獲取鏈表中第index個節(jié)點的值。如果索引無效,則返回-1。addAtHead(val):在鏈表的第一個元素之前添加一個值為val的節(jié)點。插入后,新節(jié)點將成為鏈表的第一個節(jié)點。addAtTail(val):將值為val?的節(jié)點追加到鏈表的最后一個元素。addAtIndex(index,val):在鏈表中的第index個節(jié)點之前添加值為val的節(jié)點。如果index等于鏈表的長度,則該節(jié)點將附加到鏈表的末尾。如果?index?大于鏈表長度,則不會插入節(jié)點。如果index小于0,則在頭部插入節(jié)點。deleteAtIndex(index):如果索引index?有效,則刪除鏈表中的第index?個節(jié)點。

代碼:

class MyLinkedList {

public:

struct LinkNode{

? ? ? ? int val;

? ? ? ? LinkNode* next;

? ? ? ? LinkNode(int val):val(val),next(NULL){}

? ? };

? ? MyLinkedList() {

? ? vhead=new LinkNode(0);

? ? size=0;

? ? }


? ? int get(int index) {

? ? ? if (index > (size - 1) || index < 0) {

? ? ? ? ? ? return -1;

? ? ? ? }

? ? ? ? LinkNode* cur =vhead->next;

? ? ? ? while(index--){

? ? ? ? ? ? cur = cur->next;

? ? ? ? }

? ? ? ? ? ? return cur->val;

? ? }

? ? void addAtHead(int val) {

? ? LinkNode* p=new LinkNode(val);

? ? p->next=vhead->next;

? ? vhead->next=p;

? ? size++;

? ? }


? ? void addAtTail(int val) {

? ? LinkNode* last=new LinkNode(val);

? ? LinkNode* p=vhead;

? ? while(p->next!=NULL)

? ? {

? ? ? ? p=p->next;

? ? }

? ? p->next=last;

? ? size++;

? ? }


? ? void addAtIndex(int index, int val) {

? ? ? ? if(index>size) return ;

? ? ? ? if(index<0) index=0;

? ? ? ? LinkNode *newnode=new LinkNode(val);

? ? ? ? LinkNode* p=vhead;

? ? ? ? while(index--)

? ? ? ? {

? ? ? ? ? ? p=p->next;

? ? ? ? }

? ? ? ? newnode->next=p->next;

? ? ? ? p->next=newnode;

? ? ? ? size++;

? ? }


? ? void deleteAtIndex(int index) {


? ? if(index>=size||index<0)

? ? {

? ? ? ? return ;

? ? }

? ? ? ? LinkNode* p=vhead;

? ? ? ? LinkNode* temp=p;

? ? ? ? while(index)

? ? ? ? {

? ? ? ? ? ? p=p->next;

? ? ? ? ? ? index--;

? ? ? ? }

? ? ? ? temp=p->next;

? ? ? ? p->next=temp->next;

? ? ? ? delete temp;

? ? ? ? size--;


? ? }

private:

? ? int size;

? ? LinkNode *vhead;

};

/**

* Your MyLinkedList object will be instantiated and called as such:

* MyLinkedList* obj = new MyLinkedList();

* int param_1 = obj->get(index);

* obj->addAtHead(val);

* obj->addAtTail(val);

* obj->addAtIndex(index,val);

* obj->deleteAtIndex(index);

*/

注意:

1、本題在頭節(jié)點節(jié)點之前加入了虛擬頭節(jié)點vhead,這樣在鏈表中任意一處的添加或者刪除操作都能夠保持一致性,代碼邏輯也更加簡介。

2、在刪除、添加的時候,因為單鏈表無法找到前面節(jié)點的特性,所以每個要操作的位置是p->next,也就是需要操作的前一個位置才是p。同時,為了避免出錯,可以找一個極端的例子帶入,比如index=0時,這樣寫循環(huán)條件時就不容易出錯。


LeetCode 206.反轉(zhuǎn)鏈表

題目:給你單鏈表的頭節(jié)點?head,請你反轉(zhuǎn)鏈表,并返回反轉(zhuǎn)后的鏈表。

代碼:

法一:雙指針法。定義一組指針,開始時cur指向head,pre指向head的前一個元素,因為反轉(zhuǎn)后原本的head會指向NULL,所以pre最開始指向NULL。之后cur->next會指向pre實現(xiàn)反轉(zhuǎn),然后pre、cur同時向后移動一位,繼續(xù)上述操作。注意:因為cur->next=pre時原來cur的下一個節(jié)點就斷開了,為了保證連續(xù)性,所以在cur指向pre之前,應該用一個臨時節(jié)點存著原來cur的下一個節(jié)點。

/**

* Definition for singly-linked list.

* struct ListNode {

*? ? int val;

*? ? ListNode *next;

*? ? ListNode() : val(0), next(nullptr) {}

*? ? ListNode(int x) : val(x), next(nullptr) {}

*? ? ListNode(int x, ListNode *next) : val(x), next(next) {}

* };

*/

class Solution {

public:

? ? ListNode* reverseList(ListNode* head) {

? ? ListNode* cur=head;

? ? ListNode* temp=head;

? ? ListNode* pre=NULL;

? ? while(cur!=NULL)

? ? {

? ? ? ? temp=cur->next;

? ? ? ? cur->next=pre;

? ? ? ? pre=cur;

? ? ? ? cur=temp;? ?

? ? }

? ? return pre;

? ? }

};

法二:遞歸法。這種方法本質(zhì)和雙指針是一樣的,只不過將雙指針的while函數(shù)寫成了遞歸的方式。

/**

* Definition for singly-linked list.

* struct ListNode {

*? ? int val;

*? ? ListNode *next;

*? ? ListNode() : val(0), next(nullptr) {}

*? ? ListNode(int x) : val(x), next(nullptr) {}

*? ? ListNode(int x, ListNode *next) : val(x), next(next) {}

* };

*/

class Solution {

public:

? ? ListNode* reverse(ListNode* pre,ListNode* cur)

? ? {

? ? if(cur==NULL) return pre;

? ? ListNode* temp=cur->next;

? ? cur->next=pre;

? ? return reverse(cur,temp);

? ? }

? ? ListNode* reverseList(ListNode* head) {

? ? return reverse(NULL,head);

? ? }

};

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容