1097. Deduplication on a Linked List

来源:互联网 发布:php租房管理源码 编辑:程序博客网 时间:2024/05/22 16:49

题目

Given a singly linked list L with integer keys, you are supposed to remove the nodes with duplicated absolute values of the keys. That is, for each value K, only the first node of which the value or absolute value of its key equals K will be kept. At the mean time, all the removed nodes must be kept in a separate list. For example, given L being 21→-15→-15→-7→15, you must output 21→-15→-7, and the removed list -15→15.

Input Specification:

Each input file contains one test case. For each case, the first line contains the address of the first node, and a positive N (<= 105) which is the total number of nodes. The address of a node is a 5-digit nonnegative integer, and NULL is represented by -1.

Then N lines follow, each describes a node in the format:

Address Key Next

where Address is the position of the node, Key is an integer of which absolute value is no more than 104, and Next is the position of the next node.

Output Specification:

For each case, output the resulting linked list first, then the removed list. Each node occupies a line, and is printed in the same format as in the input.

Sample Input:
00100 5
99999 -7 87654
23854 -15 00000
87654 15 -1
00000 -15 99999
00100 21 23854
Sample Output:
00100 21 23854
23854 -15 99999
99999 -7 -1
00000 -15 87654
87654 15 -1

基本思路

考察静态链表的基本操作。
1.依旧套用静态链表的常用思路。首先定义静态链表结点的结构,其中结点的性质定义变量int order;,初始化order为2*maxn 表示无效结点。为什么要2倍的maxn呢?因为本题中除了输出被保留结点的序列,还要输出被移除结点的序列。通过定义被保留结点的个数为numValid == 0 ,被移除结点的个数为numRemoved == 0,在遍历整个链表的过程中,分别给被保留结点的order赋值numValid++,给被移除结点的order赋值maxn + numRemoved++。遍历结束后,经排序,Node[0]~Node[numValid-1]是被保留的结点,Node[numValid]~Node[numValid+numRemoved-1]是被移除的结点,剩下的是无效结点。
2.总的来说,初始化order的值关键看题目要求如何输出,其目的是为了“方便分块”。若只输出一个序列,就初始化order为maxn,遍历链表时,待输出的有效结点从0开始递增;若要输出两个序列,就初始化order为2*maxn,遍历链表时,待输出序列1的有效结点从0开始递增,同时,待输出序列2的有效结点从maxn开始递增,从而自然分块了。

注意点

1.给数组的每一个元素赋相同的值有两个方法:
1)memset函数:在头文件<srting.h> 下,基本格式为memset(数组名,值,sizeof(数组名)) ,一般只用来赋值0/-1;
2)fill函数:在<algorithm> 下,基本格式如fill(array,array + 5, 6) ,即将数组array[0]~array[4]均赋值为6。

代码
#include<cstdio> #include<cstring>#include<algorithm>using namespace std;const int maxn = 100010;struct node{    int address,key,next;    int order; }Node[maxn];bool hashTable[maxn]; //标记绝对值是否出现过 bool cmp(node a,node b){    return a.order < b.order; }int main(){    for(int i=0;i<maxn;i++){//初始化链表 ,表示所有结点均为无效结点         Node[i].order = 2*maxn;    }    memset(hashTable,false,sizeof(hashTable));//初始化哈希表 ,hashTable[i]==false 表示绝对值为 i的结点没出现过     int begin,n;    scanf("%d%d",&begin,&n);//头结点地址,结点个数    int address,key,next;    for(int i=0;i<n;i++){//输入结点信息         scanf("%d%d%d",&address,&key,&next);        Node[address].address = address;        Node[address].key = key;        Node[address].next = next;    }     int p = begin,numValid = 0,numRemoved = 0;//被保留的结点个数,被移除的结点个数     while(p != -1){//遍历链表         if(hashTable[abs(Node[p].key)] == false){//结点第一次出现,            Node[p].order = numValid++;//令其order为 0,1,2...maxn-1 ,使被保留的结点在Node[]的左侧             hashTable[abs(Node[p].key)] = true;//标记         }else{//不是第一次出现             Node[p].order = maxn + numRemoved++;//令其order为 maxn,maxn+1,...,使被移除的结点在Node[]的右侧         }        p = Node[p].next;    }     sort(Node,Node+maxn,cmp);    for(int i = 0;i < numValid; i++){//输出被保留的结点         printf("%05d %d ",Node[i].address,Node[i].key);        if(i < numValid - 1) printf("%05d\n",Node[i+1].address);        else printf("-1\n");    }     for(int i = numValid;i < numValid + numRemoved; i++){//输出被移除的结点         printf("%05d %d ",Node[i].address,Node[i].key);        if(i < numValid + numRemoved - 1) printf("%05d\n",Node[i+1].address);        else printf("-1\n");    }    return 0;} 
1 0
原创粉丝点击