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

题目

在一个排序的链表中,如何删除重复的结点?例如,在图3.4(a)中重复结点被删除之后,链表如图3.4(b)所示。

思路

设置一个preNode,用于记录当前结点的前一个结点,再设置一个布尔变量needDelete,如果当前结点和后一结点的值相同(记该值为dupVal),needDelete赋值为真。

当needDelete为真时,通过循环往后找到第一个不为dupVal的结点,把该结点设置为当前结点,并赋值给preNode.next,即相当于完成了删除操作;而当needDelete为假时,把当前结点和preNode往后移一位即可。

测试算例

1.功能测试(重复结点位于链表头部、中部、尾部,无重复结点)

2.特殊测试(null,所有结点均重复)

完整Java代码

     public ListNode deleteDuplication(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;
    }

复习时写的

(含测试代码)

package _18;

/**
 * 
 * @Description 面试题18(二):删除链表中重复的结点
 *
 * @author yongh
 * @date 2018年9月18日 下午6:30:53
 */

// 题目:在一个排序的链表中,如何删除重复的结点?例如,在图3.4(a)中重复
// 结点被删除之后,链表如图3.4(b)所示。

public class DeleteDuplicatedNode {
	class ListNode{
		   int val;
		    ListNode next = null;

		    ListNode(int val,ListNode next) {
		        this.val = val;
		        this.next=next;
		    }
	}
    public ListNode deleteDuplication(ListNode pHead){
        if(pHead==null||pHead.next==null) //空结点或者仅一个结点
            return pHead;
        ListNode preNode = null;
        ListNode curNode = pHead;
        
        while(curNode!=null){
            boolean needDelete=false;
            if(curNode.next!=null && curNode.val==curNode.next.val)
                needDelete=true;
            if(!needDelete){  //当前结点不重复
                preNode=curNode;
                curNode=curNode.next;
            }else{            //当前结点重复
                int dupValue=curNode.val;
                ListNode toBeDel = curNode;
                while(toBeDel!=null&&toBeDel.val==dupValue){
                    //这里删除暂时不涉及前一结点操作,其实主要是找出后面第一个不重复结点
                    toBeDel = toBeDel.next;
                }
                if(preNode==null){  //说明删除的结点为头结点
                    pHead=toBeDel;
                }else{
                    preNode.next=toBeDel;
                }
                curNode=toBeDel;  //这个结点还是可能会出现重复的,所以不能=next
            }
        }
        return pHead;
    }
	
    
    //========测试代码======
	void test(ListNode pHead) {
		System.out.println("-----------");
		System.out.print("The original list is: ");
		ListNode curr=pHead;
		if(curr!=null) {
			while(curr.next!=null) {
				System.out.print(curr.val+",");
				curr=curr.next;
			}
			System.out.println(curr.val);
		}else {
			System.out.println();
		}
		pHead=deleteDuplication(pHead);
		System.out.print("The result list is: ");
		curr=pHead;
		if(curr!=null) {
			while(curr.next!=null) {
				System.out.print(curr.val+",");
				curr=curr.next;
			}
			System.out.println(curr.val);
		}else {
			System.out.println();
		}
		System.out.println("-----------");
	}
    
	
	/**
	 * 重复结点位于链表头部
	 */
	void test1() {
		ListNode p4=new ListNode(3, null);
		ListNode p3=new ListNode(2, p4);
		ListNode p2=new ListNode(1, p3);
		ListNode p1=new ListNode(1, p2);
		test(p1);
	}
	
	/**
	 * 重复结点位于链表尾部
	 */
	void test2() {
		ListNode p4=new ListNode(3, null);
		ListNode p3=new ListNode(3, p4);
		ListNode p2=new ListNode(2, p3);
		ListNode p1=new ListNode(1, p2);
		test(p1);
	}
	
	/**
	 * 重复结点位于链表中部
	 */
	void test3() {
		ListNode p4=new ListNode(3, null);
		ListNode p3=new ListNode(2, p4);
		ListNode p2=new ListNode(2, p3);
		ListNode p1=new ListNode(1, p2);
		test(p1);
	}
	
	/**
	 * 连续出现重复结点
	 */
	void test4() {
		ListNode p6=new ListNode(3, null);
		ListNode p5=new ListNode(3, p6);
		ListNode p4=new ListNode(2, p5);
		ListNode p3=new ListNode(2, p4);
		ListNode p2=new ListNode(1, p3);
		ListNode p1=new ListNode(1, p2);
		test(p1);
	}
	
	/**
	 * 多个重复结点
	 */
	void test5() {
		ListNode p6=new ListNode(3, null);
		ListNode p5=new ListNode(3, p6);
		ListNode p4=new ListNode(3, p5);
		ListNode p3=new ListNode(2, p4);
		ListNode p2=new ListNode(1, p3);
		ListNode p1=new ListNode(1, p2);
		test(p1);
	}
	
	/**
	 * 无重复结点
	 */
	void test6() {
		ListNode p6=new ListNode(6, null);
		ListNode p5=new ListNode(5, p6);
		ListNode p4=new ListNode(4, p5);
		ListNode p3=new ListNode(3, p4);
		ListNode p2=new ListNode(2, p3);
		ListNode p1=new ListNode(1, p2);
		test(p1);
	}
	
	/**
	 * 单个结点
	 */
	void test7() {
		ListNode p1=new ListNode(6, null);
		test(p1);
	}
    
	/**
	 * null
	 */
	void test8() {
		ListNode p1=null;
		test(p1);
	}
	
	public static void main(String[] args) {
		DeleteDuplicatedNode demo= new DeleteDuplicatedNode();
		demo.test1();
		demo.test2();
		demo.test3();
		demo.test4();
		demo.test5();
		demo.test6();
		demo.test7();
		demo.test8();
	}
    
	
	
}

-----------    The original list is: 1,1,2,3
The result list is: 2,3
-----------    -----------    The original list is: 1,2,3,3
The result list is: 1,2
-----------    -----------    The original list is: 1,2,2,3
The result list is: 1,3
-----------    -----------    The original list is: 1,1,2,2,3,3
The result list is: 
-----------    -----------    The original list is: 1,1,2,3,3,3
The result list is: 2
-----------    -----------    The original list is: 1,2,3,4,5,6
The result list is: 1,2,3,4,5,6
-----------    -----------    The original list is: 6
The result list is: 6
-----------    -----------    The original list is: 
The result list is: 
-----------

demo

收获

1.删除多个结点时,只要把重复结点前一个结点的next指向重复结点的后一个结点;

2.不要把重复结点一个一个删除,先定义一个布尔变量确定当前结点是否重复,然后按上一句话的方法进行删除即可。

**更多《剑指Offer》Java实现合集:https://github.com/gdutxiaoxu/Android_interview ******

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT徐师兄

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值