题目:用单链表保存m个整数,结点的结构为【data】【link】,且**|data|<=n(n为正整数)。现要求设计一个时间复杂度尽可能高效**的算法,对于链表中data的绝对值相等的结点,仅保留第一次出现的结点而删除其余绝对值相等的结点。
例如,若给定的单链表head如下:
关键字:带头结点单链表+删除绝对值相同的结点
思路:
关注:
要求时间高效,所以想到用空间换时间,建立辅助数组来存放符合条件的新链表 。
注(* ̄(oo) ̄):不是存放新链表!而是记录旧链表中已出现的数值,方法是:利用位序来代表某个元素的绝对值和0/1来代表是否存在。从而只需对原表进行一趟扫描。
因为|data|<=n,故辅助数组q的大小为n+1,各元素的初值均为0。
依次扫描链表中的各结点,同时检查q|data|的值,若为0则保留该结点,并令q|data|=1,否则将该结点从链表中删除
typedef struct node{
int data;
struct node *next;
}LNode;
void func(PNODE L,int n)//一个删除绝对值相同的结点的函数
{ PNODE p=L,r;//p为原表工作遍历指针,r为 指针
int *q,m;//q为指向新链表的指针,m为绝对值相同的元素的实际值(相同或相反)
q=(int*)malloc(sizeof(int)*(n+1));//给q所指向的新链表开辟空间,带头结点的一个长度为n,总长为n+1
for(int i=0;i<n+1;i++)//当i=0~n时,共计n+1次来进行以下操作
*(q+i)=0;//给q的n+1个元素全部赋值为0
while(p->next!=NULL)//p开始遍历原表
{m=p->next->data>0?p->next->data:-p->next->data;//m的值从第一个原表结点的值开始遍历,作用是将原表中所有的值全部改成其绝对值(正值)。
if(*(q+m)==0)//判断该结点的data是否出现:等于0,没有出现过,可以保留,但是要留档,之后再遇到要被删除;等于1,则出现过,需要被删除
{ *(q+m)=1;//留档
p=p->next;
}
else
{ r=p->next;//删掉p的后继结点
p->next=r->next;
free(r);
}
}
free(q);//最后释放*绝对值存在与否辅助*记录表
}