题目:
用单链表保存m个整数,节点的结构为【data,link】,且|data|<n(n为正整数)。
现要求设计一个时间复杂度尽可能高效地算法,对于链表中绝对值相等的节点,仅保留第一次出现的节点而删除其余绝对值相等的节点。
例如,若给定的单链表head如下 :
则删除节点后的head为:
要求:
(1) 给出算法的基本思想
(2) 使用c或c++语言,给出单链表节点的数据类型定义。
(3) 根据设计思想,采用c或c++语言描述算法,关键之处给出注释。
(4) 说明所涉及算法的时间复杂度和空间复杂度。
基本设计思想:
- 算法的核心思想是用空间换时间。使用辅助数组记录链表中已出现的数值,从而只需要对链表进行一趟扫描;
- 因为|data|<=n,所以辅助数组q的大小为n+1,各元素的初始值均为0。
- 依次扫描链表中各结点,同时检查q[addr](addr=|data|)的值;如果q[addr]的值为0,则保留该结点,并令q[addr]的值为1;否则将该结点从链表中删除;
单链表节点的数据类型定义:
typedef struct LNode{
int data;
struct LNode *link;
}LNode;
代码:
void simplify_list(LinkList &head,int n){
//申请n+1个位置的辅助数组;
q = (int *)malloc(sizeof(int)*(n+1));
for(int i=0;i<n+1;i++){//数组元素初值设为0;
q[i] = 0;
}
LNode *p = head->link;
pre = head;
while(p !=NULL){
int data = p->data;
int addr = data >0? data:-data;
if(q[addr] ==1){//需要删除当前节点p
temp = p;
pre->link = p->link;
p=p->link;
free(temp);
}else{//保留当前节点;
q[addr] =1;
pre = p;
p = p->link;
}
}
free(q); //释放辅助空间;
}
时间复杂度:O(m);
空间复杂度:O(n);