import java.util.HashSet;
/**
* 面试题18
* 题目二:在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。
* 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5
* @author
* @create 2021-03-21 21:14
*/
public class Solution18 {
public static void main(String[] args) {
ListNode1 listNode1 = new ListNode1(1);
ListNode1 listNode2 = new ListNode1(2);
ListNode1 listNode3 = new ListNode1(3);
ListNode1 listNode4 = new ListNode1(3);
ListNode1 listNode5 = new ListNode1(4);
ListNode1 listNode6 = new ListNode1(4);
ListNode1 listNode7 = new ListNode1(5);
listNode1.next = listNode2;
listNode2.next = listNode3;
listNode3.next = listNode4;
listNode4.next = listNode5;
listNode5.next = listNode6;
listNode6.next = listNode7;
ListNode1 res = deleteDupcationHash(listNode1);
System.out.println(res);
}
/**
* 查找时直接删除重复节点
* 时间复杂度:O(n)
* 空间复杂度:O(1)
* @param pHead
* @return
*/
public static ListNode1 deleteDupcation(ListNode1 pHead){
if (pHead == null || pHead.next == null){
return pHead;
}
//创建辅助头结点
ListNode1 head = new ListNode1(Integer.MIN_VALUE);
head.next = pHead;
ListNode1 pre = head;//维护两个指针
ListNode1 cur = head.next;
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 = cur.next;//while循环退出时cur指向重复节点,这时需要将cur指向下一个节点
pre.next = cur;//pre的next指向cur
}else {
pre = cur;
cur = cur.next;
}
}
return head.next;//pHead的next中的地址已被pre和cur修改,所以可以返回head.next
}
/**
* 使用HashSet
* 时间复杂度:HashSet 是基于哈希表实现的,查找效率为 O(1),所以总的效率是 O(n)
* 空间复杂度:最坏的情况是存一半结点 O(n/2),最好的情况是一个也不存,O(1)
* @param pHead
* @return
*/
public static ListNode1 deleteDupcationHash(ListNode1 pHead){
if (pHead == null || pHead.next == null){
return pHead;
}
HashSet<Integer> hashSet = new HashSet<>();
ListNode1 pre = pHead;
ListNode1 cur = pHead.next;
while (cur != null){
if (pre.val == cur.val){ //如果两个指针的值相等,就加入到hashset中
hashSet.add(cur.val);
}
pre = cur;//如果两个指针不相等,就向后移
cur = cur.next;
}
//先删除头结点的重复节点
while (pHead != null && hashSet.contains(pHead.val)){
pHead = pHead.next;
}
if (pHead == null){
//如果头部重复节点全部删除后为空,就直接返回
return null;
}
//再删除中间重复节点
pre = pHead;
cur = pHead.next;
while (cur != null){
if (hashSet.contains(cur.val)){
//如果hashset包含中间重复的值,就向后移
pre.next = cur.next;
cur = cur.next;
}else {
pre = cur;
cur = cur.next;
}
}
return pHead;
}
}
class ListNode1{
int val;
ListNode1 next = null;
ListNode1(int val){
this.val = val;
}
@Override
public String toString() {
return "ListNode1{" +
"val=" + val +
", next=" + next +
'}';
}
}
【剑指Offer】面试题18:删除链表中重复的节点
最新推荐文章于 2022-05-04 11:16:34 发布