【题目】
原文:
2.1 Write code to remove duplicates from an unsorted linked list.
FOLLOW UP
How would you solve this problem if a temporary buffer is not allowed?
译文:
从一个未排序的链表中移除重复的项
进一步地,
如果不允许使用临时的缓存,你如何解决这个问题?
【分析】
(1)如果可以使用额外的存储空间,我们就开一个数组来保存一个元素的出现情况。 对于这种情况,最好的解决方法当然是使用哈希表,但令人非常不爽的是C++标准里是没有 哈希表的(java里有)。所以,在这用一个数组模拟一下就好了。但,这里要注意一个问题, 就是元素的边界,比如链表里存储的是int型变量。那么,如果有负值,这个方法就不奏效 了。而如果元素里的最大值非常大,那么这个数组也要开得很大,而数组中大部分空间是用 不上的,会造成空间的大量浪费。
简言之,如果可以用哈希表,还是用哈希表靠谱。
如下代码遍历一遍链表即可,如果某个元素在数组里记录的是已经出现过, 那么将该元素删除。时间复杂度O(n):
(2)如果不允许使用临时的缓存(即不能使用额外的存储空间),那需要两个指针,cur做正常的迭代,runner指针遍历cur指针之前的所有元素,判断当前元素的值是否已经出现过。如果出现过就删除cur指向的元素。
【代码一】
/*********************************
* 日期:2014-05-17
* 作者:SJF0115
* 题目: Set Matrix Zeroes
* 来源:CareerCup
**********************************/
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
#define N 100000
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
bool Hash[N];
ListNode* DeleteDuplicatesFromUnSortedList(ListNode *head) {
if(head == NULL || head->next == NULL){
return head;
}
memset(Hash,0,sizeof(Hash));
ListNode* pre = head;
ListNode* cur = head->next;
while(cur != NULL){
//存在重复元素删除
if(Hash[cur->val]){
ListNode* node = cur;
pre->next = cur->next;
cur = cur->next;
delete node;
}
else{
Hash[cur->val] = true;
pre = cur;
cur = cur->next;
}
}
return head;
}
int main(){
int i,j;
//freopen("C:\\Users\\XIAOSI\\Desktop\\acm.txt","r",stdin);
ListNode *head = (ListNode*)malloc(sizeof(ListNode));
head->next = NULL;
ListNode *node;
ListNode *pre = head;
int A[] = {6,5,3,3,6,5,6,7,3,7,1,2,1,4,6,7,2,3};
for(int i = 0;i < 18;i++){
node = (ListNode*)malloc(sizeof(ListNode));
node->val = A[i];
node->next = NULL;
pre->next = node;
pre = node;
}
head = DeleteDuplicatesFromUnSortedList(head);
ListNode* cur = head->next;
while(cur != NULL){
printf("%d ",cur->val);
cur = cur->next;
}
return 0;
}
【代码二】
/*********************************
* 日期:2014-05-17
* 作者:SJF0115
* 题目: Set Matrix Zeroes
* 来源:CareerCup
**********************************/
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
ListNode* DeleteDuplicatesFromUnSortedList(ListNode *head) {
if(head == NULL || head->next == NULL){
return head;
}
ListNode* pre = head;
ListNode* cur = head->next;
//删除重复元素
while(cur != NULL){
ListNode* runner = head->next;
//判断是否是重复
while(runner != cur){
if(runner->val == cur->val){
ListNode* node = cur;
//删除node
pre->next = cur->next;
cur = pre->next;
delete node;
break;
}
runner = runner->next;
}
//如果上面没有删除元素,需要更新指针
if(runner == cur){
pre = cur;
cur = cur->next;
}
}
return head;
}
int main(){
int i,j;
//freopen("C:\\Users\\XIAOSI\\Desktop\\acm.txt","r",stdin);
ListNode *head = (ListNode*)malloc(sizeof(ListNode));
head->next = NULL;
ListNode *node;
ListNode *pre = head;
int A[] = {6,5,3,3,6,5,6,7,3,7,1,2,1,4,6,7,2,3};
//输入
for(int i = 0;i < 18;i++){
node = (ListNode*)malloc(sizeof(ListNode));
node->val = A[i];
node->next = NULL;
pre->next = node;
pre = node;
}
//删除重复元素
head = DeleteDuplicatesFromUnSortedList(head);
//输出
ListNode* cur = head->next;
while(cur != NULL){
printf("%d ",cur->val);
cur = cur->next;
}
return 0;
}