1. 程式人生 > 其它 >2021-1-19 刪除結點 找第一個公共結點

2021-1-19 刪除結點 找第一個公共結點

技術標籤:2021年1月

題目1 刪除連結串列中等於給定值 val 的所有節點。

x
示例:

輸入: 1->2->6->3->4->5->6, val = 6
輸出: 1->2->3->4->5

解1

常規方法,遍歷連結串列,檢視要刪除的結點
注意!
遍歷時,因為連結串列遍歷指標無法返回,所以要以遍歷結點的下一個值和刪除值進行判斷,便於刪除

class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        //1. 定義一個標記結點,指向頭,並將頭節點也賦值給該節點
ListNode* pTemp = new ListNode; pTemp->next = head; head = pTemp;//2. 遍歷連結串列,遇到刪除節點,則修改指標指向的內容 while(pTemp->next) { if(pTemp->next->val == val) pTemp->next = pTemp->next->next; else pTemp =
pTemp->next; } //3. 返回頭節點 return head->next; } };

解2

遞迴演算法,遞迴遍歷每個幾點,將遞迴返回值拼接到上一次遞迴的節點後面。

  1. 正常應該返回原結點即可;
  2. 若遇到刪除節點,則將刪除結點的下一個拼接到上一個結點
class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        if(head)
        {
        //如果未遞迴到頭,繼續深入
            head-
>next = removeElements(head->next,val); } //head的為NULL,開始返回 //返回過程中,遇到刪除結點 if(head && val == head->val) //該節點下一個返回個上一節點(即刪除了該節點) return head->next; //正常返回本結點即可 return head; } };

題目2 輸入兩個連結串列,找出它們的第一個公共節點。

如下面的兩個連結串列:
在這裡插入圖片描述

在節點 c1 開始相交。

解1 雙指標法

假設:
連結串列1長度:l1+C;連結串列2長度:l2+C;
兩個指標headA、headB分別遍歷連結串列L1,L2
當headA走到NULL時,重新賦值L2頭部,繼續遍歷;
當headB走到NULL時,重新賦值L1頭部,繼續遍歷;

當兩個連結串列走到第一個公共結點,都走l1+l2+C的長度,走的長度相同。

特殊情況

  1. 若有一個連結串列為NULL,則無交點
  2. 如下程式碼中,若兩個連結串列無交點,會進入死迴圈。通過記錄兩個連結串列最後一個結點,判斷是否相同,判斷兩連結串列有無交點
  3. 若兩個連結串列長度相同且有公共節點,同時走到最後的NULL,雖然兩指標相同,但是並非公共節點,需要繼續遍歷。
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        //1. 如果有一個連結串列為NULL,則無交點
        if(headA == NULL || headB == NULL)
            return NULL;
        //標記兩個連結串列頭
        ListNode* pA = headA;
        ListNode* pB = headB;
        //標記兩個連結串列尾
        ListNode* lA = NULL;
        ListNode* lB = NULL;
        //雙指標迴圈遍歷
        while((headA == NULL && headB == NULL) || headA != headB)
        {
            //遍歷到尾結點
            if(headA && headA->next == NULL)
                lA = headA;
            if(headB && headB->next == NULL)
                lB = headB;
            //2. 如果兩個連結串列尾都不同,則無交點
            if(lA && lB && lA!=lB)
                return NULL;
            //3. 迴圈遍歷
            headA == NULL ? headA = pB : headA = headA->next;
            headB == NULL ? headB = pA : headB = headB->next;
        }
        return headA;
    }
};

解2

設定容器<ListNode*,int>,先遍歷第一個連結串列,將每個結點對應值1;再遍歷第二個連結串列,若遍歷到的結點在容器中存在,返回該節點。

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        //==================容器法=============================
        map<ListNode*,int> nodes;
        while(headA)
        {
            nodes[headA] = 1;
            headA = headA->next;
        }
        while(headB)
        {
            if(nodes[headB])
                return headB;
            headB = headB->next;
        }
        return NULL;
    }
};

解3 快慢指標

  1. 先求兩個連結串列長度,假設相差k個元素。
  2. 再遍歷連結串列,長連結串列指標先走k步,然後兩個連結串列遍歷指標一起移動,知道結點相同