链表去重
编写代码,移除未排序链表中的重复节点。保留最开始出现的节点。
题目测评链接:leetcode.cn/problems/re…
思路1:
暴力解法,确定一个结点,遍历该节点后面的链表,是否有重复元素出现的结点,如果有就删除该节点。
时间复杂度:O(n 2) 空间复杂度:O(1)
class Solution {
public:
ListNode* removeDuplicateNodes(ListNode* head) {
ListNode* p,* q,*r;
p = head;
while(p != NULL){
q = p;
while(q->next != NULL){
if(p->val == q->next->val){
r = q->next;
q->next = r->next;
// free(r);
}else{
q = q->next;
}
}
p = p->next;
}
return head;
}
};
思路2:
如果题目限定了 结点元素值的范围,比如说 [0, 10000],我们只需要开一个 10001长度大小的bool数组 st,遍历的同时记录元素是否出现过,如果没有出现过,即st[p -> val] == false,st[p -> val] 设置为true,代表已经出现过,后面如果遇到相同存在的元素,即可删除
时间复杂度:O(n),空间复杂度:O(m)
m 表示元素的值域,比如[0, 10000] 需要开10001大小的数组,如果[0, 1e9] 需要开1e9 + 1 大小的数组
class Solution {
public:
ListNode* removeDuplicateNodes(ListNode* head) {
if(head == NULL) return head;
bool st[20010];
memset(st, false, sizeof st); // 将标记数组的全部元素初始化为false
st[head->val] = true; // 头结点设置为true
ListNode* p = head;
while(p->next != NULL){
int x = p -> next->val;
// 值为true,表示该元素出现过,要删除该结点
if(st[x]){
ListNode* q = p->next;
p->next = q->next;
// free(q);
}
// 不存在,访问下一个元素
else{
st[x] = true;
p = p->next;
}
}
return head;
}
};
进阶:
如果题目没有限定结点元素值的范围,而实际笔试的时候又不能直接调用 map, set等哈希集合这些stl容器,就需要手写 哈希表来实现查询和插入的操作
哈希表查询和插入元素,时间复杂度默认为 O1
手写哈希表,一般分为两种,开放定址法(线性探测或者二次探测),链地址法,两种都有之前手写好的模版直接套即可。
最终实现效果如下:
时间复杂度:O(n),空间复杂度:O(n)
const int N = 200003;
ListNode *ht[N];
bool find(int x){ // 哈希表查询x是否存在
int t = (x % N + N) % N;
for(auto p = ht[t]; p; p = p->next){
if(p->val == x)
return true;
}
return false;
}
void add(int a, int b){ // 单链表ht[a]中头插元素b
auto p = new ListNode(b);
p -> next = ht[a];
ht[a] = p;
}
void insert(int x){ // 单链表中插入x
if(find(x)) return;
int t = (x % N + N) % N;
add(t, x);
}
class Solution {
public:
ListNode* removeDuplicateNodes(ListNode* head) {
if(head == NULL) return head;
for(int i = 0; i < 20000; i ++) ht[i] = NULL; // 清空结构体数组
insert(head -> val); // 插入头结点
ListNode* p = head;
while(p -> next != NULL){
int x = p -> next->val;
// 值为true,表示该元素出现过,要删除该结点
if(find(x)){
ListNode* q = p->next;
p->next = q->next;
// free(q);
}
// x不存在,访问下一个元素
else{
insert(x);
p = p->next;
}
}
return head;
}
};