题目描述:

在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5

解题思路:

首先初始化一个起始指针preNode指向头结点、工作指针walkNode指向链表的第一个元素,即preNode.next=walkNode。

迭代开始:

while(walkNode!=null){

  如果当前工作结点的数据域walkNode.val与下一个结点的数据域walkNode.next.val相同(出现重复结点):

    preNode不移动;(指向重复结点段的前一个结点)

    walkNode移动:walkNode=walkNode.next;(此时preNode.next!=walkNode)

  否则,

    如果preNode.next==walkNode(说明未出现重复节点):

      preNode移动,walkNode移动:preNode=walkNode;walkNode=walkNode.next;

  否则,说明有重复结点,此时preNode指向重复结点段的前一个结点,walkNode指向重复结点段的最后一个重复结点

      使preNode直接指向重复结点段的下一个结点:preNode.next=walkNode.next;

      walkNode移动:walkNode=walkNode.next;

}

注意:因为可能会删除头结点,例如{1,1,1,2},删除了头结点1和第一个结点1,结果应为{2}。但是如果直接将函数传进来的pHead作为头结点,即初始化preNode=pHead,那么头节点永远不可能被删除,得到的结果只能为{1,2}。

因此这里添加了一个新的头节点newhead,将pHead当一般结点处理,初始化preNode=newhead这样就可以避免出现上面的错误。

举例:

1->2->3->3->4->4 (加入新头结点newhead:newhead.val=0,;ewhead.next=pHead) 0->1->2->3->3->4->4

初始化:

preNode指向新的头结点,walkNode指向第一个结点

preNode=newNode

walkNode=newhead.next

第1次迭代:

walkNode1与其下一个结点2不相同,而且preNode0和walkNode1相邻,说明之前也没有出现过重复结点,所以把两个指针都前移

walkNode.next.val!=walkNode.val&&pre.next==walkNode:pre=walkNode;walkNode=walkNode.next;

第2次迭代:

同第一次迭代

walkNode.next.val!=walkNode.val&&pre.next==walkNode:pre=walkNode;walkNode=walkNode.next;

第3次迭代:

walkNode3与下一个结点3重复,那么此时preNode不移动,只移动walkNode

walkNode.next.val==walkNode.val:walkNode=walkNode.next

第4次迭代:

walkNode3与其下一个结点4不相同,但是此时preNode和walkNode不相邻,说明preNode和walkNode中间出现了重复结点,所以把preNode直接指向walkNode的下一个结点,抛弃中间重复节点

walkNode.next.val!=walkNode.val&&pre.next!=walkNode:pre.next=walkNode.next;walkNode=walkNode.next;

第5次迭代:

walkNode4与下一个结点4重复,那么此时preNode不移动,只移动walkNode

walkNode.next.val==walkNode.val:walkNode=walkNode.next

第6次迭代:

walkNode.next==null&&pre.next!=walkNode:pre.next=walkNode.next;return newNode.next;

代码实现

 package struct;
public class deleteList {
//public class ListNode {
// int val;
// ListNode next = null;
// ListNode(int val) {
// this.val = val;
// }
//}
public ListNode printListFromTailToHead(ListNode pHead) {
ListNode newhead=new ListNode(0);//解决删除头结点的可能,例如{1,1,1,1,2}
newhead.next=pHead;
ListNode pre=newhead;
ListNode walkNode=newhead.next;
while(walkNode!=null){
if(walkNode.next!=null){
if(walkNode.next.val!=walkNode.val){
if(pre.next!=walkNode)
{
pre.next=walkNode.next;
}
else
{
pre=walkNode;
}
}
}
else{ //如果walkNode指向最后一个结点
if(pre.next!=walkNode)
{
pre.next=walkNode.next;
}
else
{
pre=walkNode;
}
}
walkNode=walkNode.next;
}
return newhead.next;
}
}

删除链表中重复的结点——牛客剑指offer的更多相关文章

  1. 链表中环的入口结点——牛客剑指offer

    题目描述: 给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null. 题目分析: 从上图中可以看出,环的入口结点和其他结点的区别:环的入口结点是有两个指针指向的,其他结点除了头结点都 ...

  2. leetcode 203. Remove Linked List Elements 、83. Remove Duplicates from Sorted List 、82. Remove Duplicates from Sorted List II(剑指offer57 删除链表中重复的结点)

    203题是在链表中删除一个固定的值,83题是在链表中删除重复的数值,但要保留一个:82也是删除重复的数值,但重复的都删除,不保留. 比如[1.2.2.3],83题要求的结果是[1.2.3],82题要求 ...

  3. [PHP] 算法-删除链表中重复的结点的PHP实现

    删除链表中重复的结点: 1.定义两个指针pre和current 2.两个指针同时往后移动,current指针如果与后一个结点值相同,就独自往前走直到没有相等的 3.pre指针next直接指向curre ...

  4. 【Java】 剑指offer(18) 删除链表中重复的结点

    本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集   题目 在一个排序的链表中,如何删除重复的结点?例如,在图3.4(a)中重 ...

  5. 《剑指offer》第十八题(删除链表中重复的结点)

    // 面试题18(二):删除链表中重复的结点 // 题目:在一个排序的链表中,如何删除重复的结点?例如,在图3.4(a)中重复 // 结点被删除之后,链表如图3.4(b)所示. #include &l ...

  6. 剑指offer-18-2. 删除链表中重复的结点

    剑指offer-18-2. 删除链表中重复的结点 链表 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针. 例如,链表1->2->3-> ...

  7. 【剑指Offer】删除链表中重复的结点 解题报告(Python)

    [剑指Offer]删除链表中重复的结点 解题报告(Python) 标签(空格分隔): 剑指Offer 题目地址:https://www.nowcoder.com/ta/coding-interview ...

  8. 链表:删除链表中重复的结点(java实现)

    题目描述 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针. 例如,链表1->2->3->3->4->4->5 处理后 ...

  9. 剑指Offer 56. 删除链表中重复的结点 (链表)

    题目描述 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针. 例如,链表1->2->3->3->4->4->5 处理后 ...

随机推荐

  1. Zabbix 4.0.2试用(七):在Linux主机中安装zabbix agent并添加该主机(yum源安装)

    Zabbix 4.0.2试用(七):在Linux主机中安装zabbix agent并添加主机(yum源安装) 2018年12月20日, 上午6:42 之前介绍的是下载源安装包,编译安装的方式来安装ag ...

  2. puppet自动化部署

    puppet自动化部署 puppet  实现运维自动化管理的软件. 官方网站: http://puppetlabs.com/    pupptet下载链接:http://downloads.puppe ...

  3. Hive运行原理--JOIN

    对于 JOIN 操作: INSERT OVERWRITE TABLE pv_users SELECT pv.pageid, u.age FROM page_view pv JOIN user u ON ...

  4. 部分和问题(dfs)

    部分和问题 描述 给定整数a1.a2........an,判断是否可以从中选出若干数,使它们的和恰好为K. 输入 首先,n和k,n表示数的个数,k表示数的和.接着一行n个数.(1<=n<= ...

  5. tomcat建立双向https安全连接

    参考:http://www.hangge.com/blog/cache/detail_992.htmltomcat连接器的框架是coyote,有关信息参考:http://blog.csdn.net/w ...

  6. 代码优化-多态代替IF条件判断

    场景描述 在开发的场景中,常常会遇到打折的业务需求,每个用户对应的等级,他们的打折情况也是不一样的.例如普通会员打9折,青铜会员打8.5折,黄金会员打8折等等.在一般开发中最简单的就是判断用户的等级, ...

  7. MySQL datetime 和 timestamp 的区别

    [转载]:MySQL中有关TIMESTAMP和DATETIME的总结 1. datetime 和 timestamp 的相同点 两者都可以用来表示YYYY-MM-DD HH:MM:SS[.fracti ...

  8. linux常用关机和重启命令

    Linux有如下的关机和重启命令:shutdown, reboot, halt, poweroff,那么它们有什么区别呢? shutdown - 建议使用的命令 shutdown是最常用也是最安全的关 ...

  9. FICO相关号码范围IMG设定

    一.定义会计文件号码范围——FBN1 二.定义总账检视的文件号码范围——FAGL_DOCNR 三.指派客户科目群组的号码范围 四.定义供应商号码范围——XKN1  五.维护订单号码范围——KONK

  10. linux常用命令(14)which命令

    我们经常在linux要查找某个文件,但不知道放在哪里了,可以使用下面的一些命令来搜索:    which  查看可执行文件的位置.   whereis 查看文件的位置.    locate   配合数 ...