一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

鏈表常見(jiàn)的題型和解題思路

 印度阿三17 2020-12-04

1.鏈表中環(huán)的入口節(jié)點(diǎn)

首先判斷頭指針是不是空的
然后需要判斷這個(gè)鏈表中包不包含環(huán):兩個(gè)指針,一個(gè)一步一個(gè)兩部,如果相遇,說(shuō)明存在
然后判斷環(huán)節(jié)點(diǎn)的個(gè)數(shù):從相遇的位置開(kāi)始,往前走并計(jì)數(shù),直到和自己再次相遇,得到個(gè)數(shù)
然后找出入口節(jié)點(diǎn):從頭開(kāi)始,倆指針一個(gè)先走n步,另一個(gè)再走,兩個(gè)相遇的位置就是入口節(jié)點(diǎn)位置

2.翻轉(zhuǎn)鏈表

需要判斷鏈表是不是空的或者鏈表是不是只有一個(gè)節(jié)點(diǎn),如果是的話(huà),直接就輸出原來(lái)的鏈表了;

如果不是的話(huà),翻轉(zhuǎn)利用循環(huán)來(lái)做,因?yàn)樾枰獙?dāng)前節(jié)點(diǎn)指向前一個(gè)節(jié)點(diǎn),所以后一個(gè)節(jié)點(diǎn)需要先保存位置,也就是需要三個(gè)指針,一個(gè)pPre,一個(gè)pCur,一個(gè)pNext:先保存后一個(gè)節(jié)點(diǎn),然后把當(dāng)前節(jié)點(diǎn)指向前一個(gè)節(jié)點(diǎn),然后把當(dāng)前節(jié)點(diǎn)變成上一個(gè)節(jié)點(diǎn),下一個(gè)節(jié)點(diǎn)變成當(dāng)前節(jié)點(diǎn);注意翻轉(zhuǎn)之后頭結(jié)點(diǎn)是原來(lái)的最后一個(gè)節(jié)點(diǎn)。

3.從尾到頭打印鏈表

思路(1):可以先翻轉(zhuǎn)鏈表,再逐個(gè)輸出

思路(2):這種具有“后進(jìn)先出”特性的,用棧比較容易,創(chuàng)建一個(gè)棧存放鏈表的節(jié)點(diǎn),存放完之后從棧頂依次取出即可

4.兩個(gè)鏈表的第一個(gè)公共節(jié)點(diǎn)

舉例子:
1 2 5 9 6 3 0
? ?7 8 9 6 3 0

首先需要知道的是,兩個(gè)鏈表從公共節(jié)點(diǎn)開(kāi)始,之后的節(jié)點(diǎn)肯定都是一模一樣的;

可以先遍歷得到兩個(gè)鏈表各自的長(zhǎng)度,然后讓長(zhǎng)的那個(gè)先走比另一個(gè)長(zhǎng)出的步數(shù),再同時(shí)走,判斷哪里相等哪里就是第一個(gè)公共節(jié)點(diǎn)了

5.鏈表中倒數(shù)第k個(gè)節(jié)點(diǎn)

單向鏈表肯定是不能從后往前數(shù)的,這個(gè)跟上面有的類(lèi)似,既然知道是倒數(shù)第k個(gè),那就兩個(gè)指針,讓一個(gè)先走k-1步,然后兩個(gè)同時(shí)走,判斷先走的那個(gè)到尾結(jié)點(diǎn)了,那后走的那個(gè)就是倒數(shù)第k個(gè)節(jié)點(diǎn)。

6.刪除鏈表中重復(fù)的節(jié)點(diǎn)

例如:1 2 3 3 4 4 5結(jié)果是1 2 5

首先需要判斷頭指針(第一個(gè)節(jié)點(diǎn))和第二個(gè)節(jié)點(diǎn)是不是空的,如果是,返回頭指針就行了;

正常情況的時(shí)候,因?yàn)橛锌赡艽嬖趧h除第一個(gè)節(jié)點(diǎn)的情況,所以需要先重新創(chuàng)建一個(gè)頭指針ListNode* newHead = new ListNode(-1),然后把這個(gè)頭指針賦初值指向原本的頭指針newHead->next = pHead;

然后需要三個(gè)指針來(lái)解決這個(gè)問(wèn)題,分別是pPre pCur pNext三個(gè),pPre 賦初值newHead,pCur賦初值pHead, 利用當(dāng)前節(jié)點(diǎn)的循環(huán)來(lái)進(jìn)行:得判斷當(dāng)前節(jié)點(diǎn)和當(dāng)前節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn)不為空才進(jìn)入循環(huán)來(lái)查找和刪除,因?yàn)槔镱^要對(duì)節(jié)點(diǎn)進(jìn)行刪除,所以要先保存下一個(gè)節(jié)點(diǎn),然后如果當(dāng)前節(jié)點(diǎn)等于下一個(gè)節(jié)點(diǎn)的值,因?yàn)檫€要繼續(xù)判斷下一位,來(lái)一個(gè)循環(huán),只要下一個(gè)節(jié)點(diǎn)和當(dāng)前節(jié)點(diǎn)的值相等,就把pNext往后移一個(gè),直到找到不相等的就退出這個(gè)查找的循環(huán)了;然后執(zhí)行刪除,也就是把上一個(gè)節(jié)點(diǎn)pPre的下一個(gè)節(jié)點(diǎn)變成pNext,當(dāng)前操作循環(huán)的節(jié)點(diǎn)變成pNext,然后再去循環(huán)判斷;

那如果當(dāng)前節(jié)點(diǎn)和下一個(gè)節(jié)點(diǎn)的值不相等呢:指針往后挪,循環(huán)再判斷,也就是pPre = pCur;pCur = pCur->next。

最后返回新的頭結(jié)點(diǎn)newHead的下一個(gè)節(jié)點(diǎn)即可。

7.復(fù)制復(fù)雜的鏈表

分成三個(gè)步驟:
(1)復(fù)制原始鏈表的任意節(jié)點(diǎn)N并創(chuàng)建新節(jié)點(diǎn)N',把節(jié)點(diǎn)N'鏈接到節(jié)點(diǎn)N的后面
(2)設(shè)置復(fù)制出來(lái)的節(jié)點(diǎn)的random,假設(shè)原始鏈表上的N的random指向節(jié)點(diǎn)S,那么其對(duì)應(yīng)復(fù)制出來(lái)的N'是N的next指向的節(jié)點(diǎn),同樣S'也是S的next指向的節(jié)點(diǎn)
(3)把整個(gè)鏈表根據(jù)奇數(shù)偶數(shù)分出兩個(gè)鏈表來(lái),偶數(shù)的就是拷貝的鏈表

/*
struct RandomListNode {
    int label;
    struct RandomListNode *next, *random;
    RandomListNode(int x) :
            label(x), next(NULL), random(NULL) {
    }
};
*/
class Solution {
public:
    RandomListNode* Clone(RandomListNode* pHead)
    {
        if(pHead == nullptr)
            return nullptr;
        //分成三個(gè)步驟:
        //1.復(fù)制原始鏈表的任意節(jié)點(diǎn)N并創(chuàng)建新節(jié)點(diǎn)N',把節(jié)點(diǎn)N'鏈接到節(jié)點(diǎn)N的后面
        //2.設(shè)置復(fù)制出來(lái)的節(jié)點(diǎn)的random,假設(shè)原始鏈表上的N的random指向節(jié)點(diǎn)S,那么其對(duì)應(yīng)復(fù)制出來(lái)的N'是N的next指向
        //的節(jié)點(diǎn),同樣S'也是S的next指向的節(jié)點(diǎn)
        //3.把整個(gè)鏈表根據(jù)奇數(shù)偶數(shù)分出兩個(gè)鏈表來(lái),偶數(shù)的就是拷貝的鏈表
        ClonedNode(pHead);
        SetRandom(pHead);
        return ReconnectNodes(pHead);
    }
    void ClonedNode(RandomListNode* pHead)
    {
        RandomListNode* pNode = pHead;
        while(pNode != nullptr)
        {
            RandomListNode* newNode = new RandomListNode(0);//創(chuàng)建新節(jié)點(diǎn)
            newNode->label = pNode->label;
            newNode->next = pNode->next;
            newNode->random = nullptr;
            pNode->next = newNode;
            pNode = newNode->next;
        }
    }
    void SetRandom(RandomListNode* pHead)
    {
        RandomListNode* pNode = pHead;
        while(pNode != nullptr)
        {
            RandomListNode* pCloned = pNode->next;
            if(pNode->random != nullptr)//這一步判斷別忘了,如果為空,會(huì)造成程序癱瘓
                pCloned->random = pNode->random->next;
            else
                pCloned->random = nullptr;
            pNode = pCloned->next;//pNode往后移一位
        }
    }
    RandomListNode* ReconnectNodes(RandomListNode* Head)
    {
        RandomListNode* pNode = Head;//循環(huán)操作
        RandomListNode* pClonedHead = nullptr;
        RandomListNode* pClonedNode = nullptr;//創(chuàng)建一個(gè)新節(jié)點(diǎn),作為拷貝鏈表的頭結(jié)點(diǎn)
        if(pNode != nullptr)
        {
            pClonedHead = pClonedNode = pNode->next;
            pNode->next = pClonedNode->next;
            pNode = pNode->next;
        }
        while(pNode != nullptr)
        {
            pClonedNode->next = pNode->next;
            pClonedNode = pClonedNode->next;
            pNode->next = pClonedNode->next;
            pNode = pNode->next;
        }
        
        return pClonedHead;
    }
};

?8.翻轉(zhuǎn)鏈表

給定一個(gè)鏈表,旋轉(zhuǎn)鏈表,將鏈表每個(gè)節(jié)點(diǎn)向右移動(dòng)?k?個(gè)位置,其中?k?是非負(fù)數(shù)。

這個(gè)題說(shuō)是翻轉(zhuǎn)鏈表,其實(shí)就是改變了鏈表的頭尾節(jié)點(diǎn)而已。

(1)先判斷特殊情況,比如鏈表是否為空,是否只有一個(gè)元素,翻轉(zhuǎn)的k是否為0等,否則直接返回

(2)然后處理一般情況,得先遍歷一次得到鏈表的總長(zhǎng)度size,然后將鏈表首尾相接,成為一個(gè)循環(huán)鏈表

(3)根據(jù)size和k的關(guān)系,計(jì)算出循環(huán)鏈表循環(huán)的次數(shù)loot= size - (k%size);

(4)然后進(jìn)行指針循環(huán),之前的頭尾節(jié)點(diǎn)指針開(kāi)始移動(dòng),次數(shù)為loop,直到移動(dòng)結(jié)束,原先的尾結(jié)點(diǎn)指針指向的為新鏈表的尾部,原先的頭結(jié)點(diǎn)指針指向的為新鏈表的頭部。

9.扁平化多級(jí)雙向鏈表

多級(jí)雙向鏈表中,除了指向下一個(gè)節(jié)點(diǎn)和前一個(gè)節(jié)點(diǎn)指針之外,它還有一個(gè)子鏈表指針,可能指向單獨(dú)的雙向鏈表。這些子列表也可能會(huì)有一個(gè)或多個(gè)自己的子項(xiàng),依此類(lèi)推,生成多級(jí)數(shù)據(jù)結(jié)構(gòu),如下面的示例所示。

給你位于列表第一級(jí)的頭節(jié)點(diǎn),請(qǐng)你扁平化列表,使所有結(jié)點(diǎn)出現(xiàn)在單級(jí)雙鏈表中。

?

?這題太經(jīng)典了!

/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* prev;
    Node* next;
    Node* child;
};
*/

class Solution {
public:
    vector<Node*> v;
    //這題就是二叉樹(shù)的前序遍歷
    //可以先前序遍歷,將所有節(jié)點(diǎn)放入容器中,然后再順序進(jìn)行前后連接
    void dfs(Node* head)
    {
        if(head == nullptr)
            return;
        v.push_back(head);
        dfs(head->child);
        dfs(head->next);
    }
    Node* flatten(Node* head) {
        dfs(head);//這樣就將所有的節(jié)點(diǎn)放入了容器中,按照前序的方式
        int n = v.size();//得到容器中的節(jié)點(diǎn)數(shù)
        for(int i=0;i<n;i  )
        {
            if(i<n-1)
                v[i]->next = v[i 1];
            if(i>0)
                v[i]->prev = v[i-1];
            v[i]->child = nullptr;
        }
        return head;

    }
};

?

10.判斷是不是回文鏈表

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    bool isPalindrome(ListNode* head) {
        //先判斷特殊情況
        if(head == nullptr || head->next == nullptr)
            return true;
        //然后一般情況的判斷方式是:先找到鏈表的中點(diǎn),然后翻轉(zhuǎn)后半部分,然后進(jìn)行比較
        ListNode* fast = head;
        ListNode* slow = head;
        while(fast != nullptr)
        {
            slow = slow->next;
            fast = fast->next? fast->next->next : fast->next;
        }
        //最后的slow為原來(lái)鏈表的中間節(jié)點(diǎn),也是待會(huì)兒需要翻轉(zhuǎn)鏈表的頭結(jié)點(diǎn)
        //fast則指向了nullptr
        
        //然后需要進(jìn)行翻轉(zhuǎn)
        ListNode* pPre = nullptr;
        while(slow != nullptr)
        {
            ListNode* temp = slow->next;//存儲(chǔ)下一個(gè)節(jié)點(diǎn)
            slow->next = pPre;
            pPre = slow;
            slow = temp;
        }
        //然后進(jìn)行判斷
        while(pPre != nullptr && head != nullptr)
        {
            if(pPre->val != head->val)
                return false;
            pPre = pPre->next;
            head = head->next;
        }
        return true;


    }
};
? ?

tips:遇到鏈表為題時(shí)候的思考方式

(1)是否能用雙指針解決

(2)知否可以將一個(gè)指針先走幾步,再兩個(gè)同時(shí)走解決

(3)是否需要知道鏈表節(jié)點(diǎn)的個(gè)數(shù)

(4)是否需要將鏈表變成循環(huán)鏈表處理

(5)考慮是否需要容器,容器可以放節(jié)點(diǎn),容器的好處也是能知道鏈表的長(zhǎng)度

(6)找鏈表的中點(diǎn)、翻轉(zhuǎn)鏈表都是最基本的操作,在拔高的題目里頭有可能會(huì)用到

來(lái)源:https://www./content-4-774451.html

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多

    亚洲视频一区二区久久久| 精品推荐国产麻豆剧传媒| 精品精品国产自在久久高清| 亚洲中文字幕日韩在线| 亚洲第一区二区三区女厕偷拍| 欧美国产在线观看精品| 三级理论午夜福利在线看| 妻子的新妈妈中文字幕| 一区二区三区人妻在线| 欧美偷拍一区二区三区四区| 久草热视频这里只有精品| 亚洲天堂一区在线播放| 欧美日韩国产精品自在自线| 欧美日本道一区二区三区| 福利专区 久久精品午夜| 老富婆找帅哥按摩抠逼视频| 亚洲熟女熟妇乱色一区| 不卡视频在线一区二区三区| 日韩中文字幕免费在线视频| 免费精品一区二区三区| 91人妻久久精品一区二区三区| 99久久免费中文字幕| 婷婷一区二区三区四区| 亚洲最新一区二区三区| 国产精品免费无遮挡不卡视频| 日本91在线观看视频| 国产又粗又猛又大爽又黄同志| 中文字幕精品一区二区年下载| 色涩一区二区三区四区| 国产精品午夜福利免费阅读 | 人妻一区二区三区在线| 精品久久久一区二区三| 欧美日韩乱一区二区三区| 欧美日韩乱码一区二区三区| 欧美一区二区三区五月婷婷 | 色综合视频一区二区观看| 成人免费观看视频免费| 美女极度色诱视频在线观看| 国产一区一一一区麻豆| 日韩一区欧美二区国产| 日韩亚洲精品国产第二页|