劍指Offer(八)刪除鏈表的節點 刪除鏈表重複節點

劍指offer(八) 刪除鏈表的節點 刪除鏈表重複節點

題目:

給定單向鏈表的頭指針和一個節點指針 定義一個函數在O(1)時間內刪除該節點

思路:

遍歷一遍等於白給 O(n)

假設 1-2-3-4-5-6-7-8-9

當刪除 2 這個節點的時候, 把2 之後的第一個節點3複製到一個temp節點,然後將temp 這個節點裏的值複製給2,將temp的指針賦給 2 ,也就是2 節點的值變爲3,其指向變成了4.

3-4-5-6-7-8-9

1 - 2 -3-4-5-6-7-8-9 刪除之後就 相當於1-3-4-5-6-7-8-9

對於n-1個非尾節點,我們可以在0(1)內將後一個節點複製覆蓋給刪除的節點,對於最後一個節點,我們還是需要去遍歷鏈表找到他,複雜度還是0(n)

平均時間複雜度 【(n-1)* O(1) + O(n) 】 / n

總的平均時間複雜度爲 O(1)

代碼:


public void deleteNode(ListNode head, ListNode node)
{
    if (head==null||node==null)
    //輸入有誤  返回
    {
       return;
    }
    if (head==node)
    //刪除節點就是頭節點
    {
        head =null;
        node = null;
        return;
    }
    if (node.next!=null)
    //刪除節點在鏈表中
    {
        ListNode node1 = node.next;
            //node1 此時是待刪節點的下一個節點
            node.val = node1.val;
            // 將待刪節點的下一個節點 的 val 賦值給  待刪節點
            node.next = node1.next;
            //將待刪節點的下一個節點 的 指針 賦給 待刪節點
        }else
    {
        ListNode temp=head;
        while(temp.next!=node)
                 temp=temp.next;
        temp.next=null;
    }
}

題目:

在一個排序的鏈表中 如何刪除重複的節點?

例如:1 -> 2 -> 3 -> 3 -> 4
刪除後是 1 -> 2 -> 4

思路:

維持兩個指針,一個指針爲要當前節點的前一個指針,一個指向當前節點.

首先初始化,pre指針爲null,而cur指針指向鏈表的頭.

當cur指向的節點的next不爲空,也就是它不只有一個節點,繼續

​ 不爲空,且當前節點和下一個節點的值相同,即重複

​ while循環,直到找到一個和當前節點的值不一樣的節點

​ 如果pre==null 那就說明已經遍歷的所有節點都是重複的

​ 將當前節點作爲phead 節點

​ 如果pre != null

​ 將 pre的next指向當前節點.

​ 沒有和下一個節點相同.沒有重複

​ pre指向當前節點,cur指向下一個節點.繼續遍歷

代碼:

    //刪除鏈表裏的重複節點
    //非遞歸版本
    public static ListNode deleteRepeatNode1(ListNode pHead)
    {
        ListNode pre = null;
        ListNode cur = pHead;
        while (cur != null)
        {
            if (cur.next != null && cur.next.val == cur.val)
            {
                while (cur.next != null && cur.next.val == cur.val)
                {
                    cur = cur.next;
                }
                cur = cur.next;
                if (pre == null) pHead = cur;
                else pre.next = cur;
            }
            else
            {
                pre = cur;
                cur = cur.next;
            }
        }
        return pHead;
    }
    //https://www.cnblogs.com/yongh/p/9672004.html#_label2

//刪除鏈表裏的重複節點
    //遞歸版本
    public static ListNode deleteDuplication(ListNode pHead)
    {
        if (pHead==null)
        //輸入有誤  返回
        {
            return null;
        }
        ListNode next=pHead.next;
        if(pHead.val==next.val)
        {
            while(next!=null&&pHead.val==next.val)
                //需要先判斷是否爲空
            {
                next=next.next;
                //找到下一個
            }
            return deleteDuplication(next);
        }else
        {
            pHead.next=deleteDuplication(next);
            return pHead;
        }
    }


public static void main(String[] args)
    {
        ListNode node1 = new ListNode(1);
        ListNode node2 = new ListNode(2);
        ListNode node3 =new ListNode(3);
        ListNode node4 =new ListNode(3);
        ListNode node5 =new ListNode(3);
        ListNode node6 =new ListNode(3);
        ListNode node7 =new ListNode(3);

        node1.next=node2;
        node2.next=node3;
        node3.next=node4;
        node4.next=node5;
        node5.next=node6;
        node6.next=node7;

        ListNode old = node1;
        while (old!=null)
        {
            System.out.print(" "+old.val );
            old=old.next;
        }
        System.out.println();
        deleteDuplication(node1);

        while (node1!=null)
        {
            System.out.print(" "+node1.val );
            node1=node1.next;
        }
    }

測試用例

我們測試要儘可能的全面
1)傳NULL
2)只有一個節點
3)頭節點開始就有重複
4)中間節點重複
5)尾部節點重複
6)鏈表中沒有重複鏈表
7)所有節點都是重複的

https://blog.csdn.net/gangstudyit/article/details/80623477

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章