题目:

逆序数-冯金伟博客园



分析:

题目给出了一段序列,要我们还原出原序列。由于原序列是在1n范围内,并且是由1n组成的,所以我们可以先给出一个1n的递增序列List,然后按照一定的规则重新排列,就能得到原序列。而这个排序规则就是根据逆序列来的。一个数a的逆序数表示的是在原序列中,a后面的数中比a小的数的个数。那么反过来,如果给出一个逆序数b,我们只要在List中从小到大数b个数,那么下一个数就是b对应的原来的数。要注意每找一个原来的数后,就要把这个数删除。按照这个思路,可以用数组实现,也可以用链表来做,这里采用的是链表。如果用链表,那么这道题就相当于是:创建一个长度为n的链表,链表的数据依次为从1n,然后根据逆序列,对每一个逆序数b,指针从头开始往右移动b次,输出下一个结点的数据,并删除该节点。这样就可以了。



代码:

#include<iostream>
#include<stdlib.h>
using namespace std;

struct Numlist
{
    int data;
    Numlist *next;
 };

int main()
{
    int i,j,n,a[500],out[500];
    Numlist *p,*newp,*p1,*head;

    head=(Numlist*)malloc(sizeof(Numlist));
    head->next=NULL;
    p=head;

    cin>>n;

    for(i=0;i<n;i++)
	    cin>>a[i];

    for(i=0;i<n;i++)                                     //创建一个长度为n的链表,数据依次为1~n
    {
	    newp=(Numlist*)malloc(sizeof(Numlist));
	    newp->data=i+1;
	    p->next=newp;
	    newp->next=NULL;
	    p=p->next;
    }

    for(i=0;i<n;i++)
    {
	    p=head;
	    for(j=0;j<a[i];j++)                     //指针后移逆序数次
		    p=p->next;
	    p1=p->next;
	    out[i]=p1->data;                       //记录下一个结点的数据
	    p->next=p1->next;                      //删除该节点
	    delete p1;                      
    }

    for(i=0;i<n;i++)
	    cout<<out[i]<<" ";
	
    return 0;
 }