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