【题目一】 力扣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;
}