[剑指Offer]删除链表中重复的结点(Java)

题目

删除链表中重复的结点 -- newcoder 剑指Offer 56

 

题目描述

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

 

思路

     * 1、新建前驱节点,next指向pHead,方便处理头节点元素重复的场景
     * 2、双指针,一个pre指针指向前一个不重复的节点,一个cur指向当前遍历的节点,分情况处理
     * 3、当遍历到重复的节点时,pre指针的next指向当前重复节点的最后一个节点的next,即删除重复元素,cur指针后移
     * 4、当遍历到不重复的节点,只需要pre、cur指针同时后移即可

 

代码

package com.codinginterviews.list;

/**
 * 题目:
 * 删除链表中重复的结点 -- newcoder 剑指Offer 56
 * 
 * 题目描述:
 * 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,
 * 返回链表头指针。 
 * 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5
 *
 */
public class DeleteDuplication {
	static class ListNode {
		int val;
		ListNode next;
		public ListNode(int val) {
			this.val = val;
		}
		
		// 便于打印不能作用与循环链表
        @Override
        public String toString() {
            if (this.next == null) {
                return String.valueOf(this.val);
            }
            return this.val + "->" + this.next.toString();
        }
	}
	
 
	
	/**
	 * 题目:
	 * 删除链表中所有重复的元素  0->1->1->2  =>   0->2 
	 * 
	 * 思路:
	 * 1、新建一个临时头节点,避免头节点是重复元素时,特殊处理
	 * 2、返回链表头节点
	 */
	public static ListNode deleteDuplication(ListNode pHead) {
		if (pHead == null) {
			return pHead;
		}
		
		// 临时头节点
		ListNode root = new ListNode(-1);
		root.next = pHead;
		
		// 两个指针
		ListNode preNode = root;
		ListNode curNode = pHead;
		
		while (curNode != null && curNode.next != null) {
			// 遇到重复节点,则遍历所有相同节点,pre->next 指向 最后一个相同节点的next
			if (curNode.val == curNode.next.val) {
				while (curNode != null && curNode.next != null && curNode.val == curNode.next.val) {
					curNode = curNode.next;
				}
				// curNode此时为重复元素中的最后一个元素
				// 删除重复元素
				preNode.next = curNode.next;
			} else {
				preNode = curNode;
			}
			// 后移curNode
			curNode = curNode.next;
		}
		
        return root.next;		
	}
	
	/**
	 * 思路:
	 * 1、新建前驱节点,next指向pHead,方便处理头节点元素重复的场景
	 * 2、双指针,一个pre指针指向前一个不重复的节点,一个cur指向当前遍历的节点,分情况处理
	 * 3、当遍历到重复的节点时,pre指针的next指向当前重复节点的最后一个节点的next,即删除重复元素,cur指针后移
	 * 4、当遍历到不重复的节点,只需要pre、cur指针同时后移即可
	 */
    public static ListNode deleteDuplicationII(ListNode pHead){
        if(pHead == null || pHead.next == null) {
            return pHead;
        }
        ListNode root = new ListNode(-1);
        root.next = pHead;
        
        ListNode pre = root;
        ListNode cur = pHead;
        
        while (cur != null) {
            boolean dup = false;
            while (cur.next != null && cur.val == cur.next.val) {
                dup = true;
                cur = cur.next;
            }
            if (dup) {
                pre.next = cur.next;
                cur = cur.next;
            } else {
                pre = cur;
                cur = cur.next;
            }
        }
        return root.next; 
    }
	
/**
 * ==========================================================================
 * 下面两个题目为删除重复元素,但是保留其中之一
 * ==========================================================================
 * 	
 */
	
	
	/**
	 * 题目:
	 * o(n)时间  有序的链表删除重复元素,保留第一个重复的元素
	 * 0->1->1->2  =>   0->1->2 
	 * 
	 * 思路:
	 * 1、遍历链表,一个指针指向前驱节点  一个指向下一个节点
	 * 2、返回新的链表(新链表,头结点引用)
	 * 
	 */
	public static ListNode deleteDuplicationReamainFirstOne(ListNode pHead) {
		if (pHead == null) {
			throw new RuntimeException("link is empty");
		}
		
		ListNode root = new ListNode(-1);
		root.next = pHead;
		
		ListNode pre = root;
		ListNode curNode;
		
		while (pre != null) {
			curNode = pre.next;
			// 元素重复时 删除后续重复元素
			if (curNode != null && pre.val == curNode.val) {
				pre.next = curNode.next;
			// 不重复时 pre后移一位
			} else {
				pre = pre.next;
			}
		}
		
		return root.next;
	}
	
	
	/**
	 * 题目:
	 * o(n)时间  有序的链表删除重复元素,保留最后一个重复的元素
	 * 0->1->1->2  =>   0->1->2 
	 * 
	 * 思路:
	 * 1、遍历链表,一个指针指向前驱节点 一个指向当前节点
	 * 2、返回新的链表(新链表,头结点引用)
	 * 
	 */
	public static ListNode deleteDuplicationRemainLastOne(ListNode head) {
		if (head == null) {
			throw new RuntimeException("link is empty");
		}
		
		ListNode newHead = head;
		
		ListNode preNode = newHead;
		ListNode curNode = newHead.next;
	
		// 当头结点与下一结点值相同,需要删除头结点及后续相同节点
		if (preNode.val == curNode.val) {
			while (preNode.val == curNode.val) {
				preNode = preNode.next;
				curNode = curNode.next;
			}
			newHead = preNode;
		}
		
		// 头结点与下一结点值不同
		while (curNode != null && curNode.next != null) {
			if (curNode.val != curNode.next.val) {
				preNode = curNode;
			} else {
				preNode.next = curNode.next;
			}
			curNode = curNode.next;
		}
		
		return newHead;
	}
	
    public static void main(String args[]) {
        
		ListNode head = createTestLinkedList(5, new ListNode(4));
        // 原链表
        System.out.println("origin link: " + head);
 
        // 删除重复元素
        System.out.println("remove repeat node: " + deleteDuplicationII(head));
 
        
		ListNode head1 = createTestLinkedList(5, new ListNode(4));
        // 删除重复元素,保留第一个重复的元素
        System.out.println("remove repeat node but left first one: " + deleteDuplicationReamainFirstOne(head1));
        
        
		ListNode head2 = createTestLinkedList(5, new ListNode(4));
        // 删除重复元素,保留最后一个重复的元素
        System.out.println("remove repeat node but left last one: " + deleteDuplicationRemainLastOne(head2));
        
    }
    
    private static ListNode createTestLinkedList(int n, ListNode addNode) {
        ListNode head = new ListNode(0);
        ListNode head1 = new ListNode(0);
        head.next = head1;
        ListNode curNode = head1;
        int count = 1;
        for (int i = 1; i < n; i++) {
            curNode.next = new ListNode(i);
            curNode = curNode.next;
            if (i == 2 && count >= 0) {
            	i--;
            	count--;
            }
        }
        curNode.next = addNode;
        return head;
    }
 
}

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值