链表的重复节点删除

【题目一】 力扣83  删除重复的节点(保留重复的节点)
给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次。
示例 1:
输入:
1->1->2
输出: 1->2

示例 2:
输入:
1->1->2->3->3
输出: 1->2->3

【解法1】使用set去重,思路很简单。时间复杂度O(N),空间复杂度O(N)

public static ListNode deleteRepeatedNode1(ListNode head) {
		if (head == null) {
			return head;
		}
		ListNode cur = head.next;
		ListNode pre = head;
		Set<Integer> set = new HashSet<>();
		set.add(head.val);// 保留第一个节点
		while(cur != null){
			if (!set.contains(cur.val)) {
				set.add(cur.val);
				pre.next = cur;
				pre = pre.next;
			}else {
				pre.next = cur.next;
			}
			cur = cur.next;
		}
		return head;
	}
	

【解法2】遍历链表,一次去重重复的节点。

方法二:类似选择排序的过程,时间复杂度为 O(N2),额外空间复杂度为 O(1)。

  •  链表 1->2->3->3->4->4->2->1->1->null。
  •  首先是头节点,节点值为 1,往后检查所有值为 1 的节点,全部删除。链表变为:1->2->3->3->4->4->2->null。
  •  然后是第二个节点,节点值为 2,往后检查所有值为 2 的节点,全部删除。链表变为:1->2->3->3->4->4->null。
  •  接着是第三个节点,节点值为 3,往后检查所有值为 3 的节点,全部删除。链表变为:1->2->3->4->4->null。
  •  最后是第四个节点,节点值为 4,往后检查所有值为 4 的节点,全部删除。链表变为:1->2->3->4->null。
public static ListNode deleteRepeatedNode2(ListNode head) {
		ListNode cur = head;
		ListNode pre = null;
		ListNode next = null;
		while(cur != null){
			pre = cur;
			next= cur.next;
			while(next != null){
				if (cur.val == next.val) {
					pre.next = next.next;// 删除next节点  很关键
				}else {
					pre = next;
				}
				next = next.next;
			}
			cur = cur.next;
		}
		return head;
	}

【题目儿】 力扣82  删除重复的节点(不保留重复的节点)
给定一个排序链表,删除所有含有重复数字的节点,只保留原始链表中 没有重复出现 的数字。(注意链表已经排序了)
示例 1:
输入:
1->2->3->3->4->4->5
输出: 1->2->5

示例 2:
输入:
1->1->1->2->3
输出: 2->3

【解法一】使用map统计每个节点出现的次数

public static ListNode deleteRep1(ListNode head){
		ListNode pre = new ListNode(-1);
		ListNode temp = pre;
		ListNode cur = head;
		Map<Integer, Integer> map = new HashMap<>();		
		while (cur != null) {
			map.put(cur.val, map.getOrDefault(cur.val, 0) + 1);
			cur = cur.next;
		}
		cur = head;
		while(cur!= null){
			if (map.get(cur.val) == 1) {
				temp.next = cur;
				temp = temp.next;
			}else {
				temp.next = cur.next;// 这一步很重要啊!!!  对于结尾的处理   如果没有else,对于1-2-2  这种情况会得到  1-2-2
			}
			cur = cur.next;
		}
		return pre.next;
	}

【解法二】使用双指针,如果两个指针指向的链表值不相等时,两个指针之间的距离大于0,就说明存在重复值,否则就没有重复值。

这种情况只有一个需要注意的地方就是  temp节点更新的条件,只有len=0时才进行更新。(主要时考虑1-1-2-2-3这种情况,重复的数据的相连的,如1和2都需要删除。)

public static ListNode deleteRep2(ListNode head){
		if (head == null || head.next == null) {
			return head;
		}
		ListNode pre = new ListNode(-1);
		pre.next = head;// 设置哨兵节点
		ListNode temp = pre;
		ListNode cur = head;
		ListNode next = cur.next;
		int len = 0;// next节点和cur节点之间的距离,大于1则有重复节点
		while (next != null) {
			while (next != null && cur.val == next.val) {// 如果相等,next 向下走
				len++;// 间距
				next = next.next;
			}
			if (len == 0) {// 没有重复的节点
				temp.next = cur;
				temp = temp.next;//只有这种情况才能更新temp 就是说temp=temp.next不能放到  if else 代码语句的后面, 对于1-1-2-2-3这种情况的避免
			} else {// 有重复节点
				len = 0;// 重置节点间距
				temp.next = next;
			}
			cur = next;
			if (next != null) next = cur.next;//注意为节点的判断
		}
		return pre.next;
	}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值