劍指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