删除链表中重复的元素
方法一:直接删除重复的节点
图解:
思路:
1.判断链表是否为空,如果为空,就直接返回null
2.由于进行删除,所以可以定义一个虚的头结点
3.遍历链表,如果遇到前后两个节点相等,就进行内循环,找到不重复的点
4.将重复的点跳过
** 代码:**
import java.util.*;
public class Solution {
public ListNode deleteDuplicates (ListNode head) {
//判断一下如果链表为空,就直接不需要进行删除,返回null
if(head==null){
return null;
}
//由于进行删除操作的时候,头结点很特殊,所以可以通过设置一个虚的头结点,连接到原来的表上
ListNode dummynode=new ListNode(-1);
dummynode.next=head;
ListNode cur=dummynode;
//遍历整个表,只要当前的节点的下一个节点和下下个节点不为空,就继续进行循环
//当遇到cur.next.val==cur.next.next.vald的时候,就需要进行一个内层的循环,跳过重复的点
//只要cur后面还有节点,并且那个点的值与前面的值相等,那么就跳过这些点
while(cur.next!=null&&cur.next.next!=null){
if(cur.next.val==cur.next.next.val){
int temp=cur.next.val;
while(cur.next!=null&&cur.next.val==temp){
cur.next=cur.next.next;
}
}else{
//否则如果不存在重复的就直接指向相邻的下一个节点
cur=cur.next;
}
}
return dummynode.next;
}
}
方法二:哈希(适用于有序无序的链表的去重)
思路:
这道题幸运的是链表有序,我们可以直接与旁边的元素比较,然后删除重复。那我们扩展一点,万一遇到的链表无序呢?我们这里给出一种通用的解法,有序无序都可以使用,即利用哈希表来统计是否重复。
**具体做法:
step 1:遍历一次链表用哈希表记录每个节点值出现的次数。
step 2:在链表前加一个节点值为0的表头,方便可能的话删除表头元素。
step 3:再次遍历该链表,对于每个节点值检查哈希表中的计数,只留下计数为1的,其他情况都删除。
step 4:返回时去掉增加的表头。
java代码:
import java.util.*;
public class Solution {
//用哈希的方法:适用于有序和无序的链表的去重
public ListNode deleteDuplicates (ListNode head) {
//先判断一下链表如果是空,就不需要进行删除,直接返回null
if(head==null){
return null;
}
//否则就创建一个HashMap
//将对应节点的数值和该节点出现的个数存入map中
Map<Integer,Integer> map=new HashMap<>();
ListNode cur=head;
while(cur!=null){
if(map.containsKey(cur.val)){
map.put(cur.val,(int)map.get(cur.val)+1);
}else{
map.put(cur.val,1);
}
cur=cur.next;
}
//由于要进行删除操作,又由于头结点是特殊的,所以可以定义一个虚的头结点
//连接到原链表上
//遍历链表的节点,如果发现该节点出现的次数不止一次,就跳过该节点
ListNode dummynode=new ListNode(-1);
dummynode.next=head;
cur=dummynode;
while(cur.next!=null){
if(map.get(cur.next.val)!=1){
cur.next=cur.next.next;
}else{
cur=cur.next;
}
}
return dummynode.next;
}
}
c++代码:
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};
*/
class Solution {
public:
ListNode* deleteDuplication(ListNode* pHead) {
if(pHead==NULL){
return pHead;
}
//定义一个哈希表:unordered_map是没有进行排序的只是类似数组的一一映射的关系
//所以是可以通过直接调用下标来获得值的
//而对于红黑树:map,是根据关键字进行排序的,是没有直接引用下标的
//定义一个哈希表:对应的额两个是某个节点的值对应的出现的次数
unordered_map<int,int> mp;
ListNode* cur=pHead;
//遍历整个链表,将对应的值记录到哈希表中
while(cur!=NULL){
mp[cur->val]++;
cur=cur->next;
}
//进行删除操作和建立一个新表的时候,为了方便处理头结点
//可以设置一个虚的头结点,将该虚的头结点连接到原链表的头结点
ListNode* dummynode=new ListNode(-1);
dummynode->next=pHead;
cur=dummynode;
//遍历每个节点,将个数不是1的节点跳过
while(cur->next!=NULL){
if(mp[cur->next->val]!=1){
cur->next=cur->next->next;
}else{
cur=cur->next;
}
}
return dummynode->next;
}
};