逆序数还原c语言 输入数组 2 0 1 0 0 输出原序数 3 1 4 2 5

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了逆序数还原c语言 输入数组 2 0 1 0 0 输出原序数 3 1 4 2 5相关的知识,希望对你有一定的参考价值。

本题的逆序数就是后面比它小的数


那么从前往后看


第一个的数的逆序数是a1


表示后面有a1个比其小


因为前面又没有数


所以它是第a1+1大的数,也就是a1+1


对于第二个数a2,表示第二个数是后面第a2+1小的


如果a2+1大于第一个数,要是后面有a2个比当前数小,那么就要是a2+2了


第三个第四个以此类推


对于数列数很小的时候,可以从左到右每次都选择没出现过的第ai+1大的数

#include <stdio.h>
#include <string.h>
#define MAXN 5000
int vis[MAXN];
int a[MAXN];
int res[MAXN];
int main()
int n,i,j,k;
printf("请输入数的个数n:");
scanf("%d",&n);
printf("请输入n个数:\\n");
for(i=0;i<n;i++)
    scanf("%d",a+i);
memset(vis,0,sizeof(vis));
for(i=0;i<n;i++)
    j=0;
    k=0;
while(k<a[i]+1)
j++;
if(vis[j]==1) continue;
k++;

vis[j]=1;
res[i]=j;

printf("结果:\\n");
for(i=0;i<n;i++)
printf("%d ",res[i]);
printf("\\n");
return 0;

这个算法的时间复杂度在O(n^2)


在n很大的时候,这个方法需要的时间太长,就不太合适了


在上个算法中,查找剩余数种第ai+1大的数是这样的:

while(k<a[i]+1)
    j++;
    if(vis[j]==1) continue;
    k++;


可以对这一部分进行优化


如果把没有用过的数标为1,用过的数标为0


那么要找的第k大的数,就是前缀和等于k的数


如果用一棵线段树来维护一个前缀和,当某节点左子树的前缀和小于k的时候,直接找右子树就可以了


具体见代码

#include <stdio.h>
#include <string.h>
#define MAXN 100000
int a[MAXN];
int res[MAXN];
typedef struct
int sum;
int left,right;
Node; 
Node tree[MAXN<<2];//开4倍空间
void build(int id,int left,int right)
tree[id].left=left;
tree[id].right=right;
if(left==right)
tree[id].sum=1;
return;

int mid=(left+right)>>1;
build(id<<1,left,mid);
build(id<<1|1,mid+1,right);
tree[id].sum=tree[id<<1].sum+tree[id<<1|1].sum;

void update(int id,int pos,int val)
int left=tree[id].left;
int right=tree[id].right;
if(left==right)
tree[id].sum=0;
return;

int mid=(left+right)>>1;
if(pos<=mid) update(id<<1,pos,val);
else update(id<<1|1,pos,val);
tree[id].sum=tree[id<<1].sum+tree[id<<1|1].sum;

int query(int id,int val)
int left=tree[id].left;
int right=tree[id].right;
if(left==right) return left;
if(tree[id<<1].sum<val)
return query(id<<1|1,val-tree[id<<1].sum);
return query(id<<1,val);

int main()
int n,i,j;
printf("请输入数的个数n:");
scanf("%d",&n);
printf("请输入n个数:\\n");
for(i=0;i<n;i++)
    scanf("%d",a+i);
build(1,1,n);
for(i=0;i<n;i++)
    j=query(1,a[i]+1);
    res[i]=j;
    update(1,j,0);

printf("结果:\\n");
for(i=0;i<n;i++)
printf("%d ",res[i]);
printf("\\n");
return 0;

这个算法的时间复杂度是O(nlogn),对于几十万的数据,秒出结果不成问题。

参考技术A #include "stdafx.h"
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <time.h>
#include<string.h>

int c[1001],a[1200];
int n;
int low(int x)

return x&(-x);

int sum(int x)

int cnt=0;
while(x>0)

cnt+=c[x];
x-=low(x);

return cnt;

void add(int x,int num)

while(x<=n)

c[x]+=num;
x+=low(x);


int main()

int num;
while(scanf("%d",&n)!=EOF)

memset(c,0,sizeof(c));
for(int i=1;i<=n;i++)
add(i,1);
for(int i=1;i<=n;i++)

scanf("%d",&num);
num++;
for(int j=1;j<=n;j++)
if(sum(j)==num)

a[i]=j;
add(j,-1);
break;


for(int i=1;i<=n;i++)

if(i!=1)
printf(" ");
printf("%d",a[i]);

printf("\\n");

return 0;

参考技术B 我没懂什么意思,能具体一点吗? 参考技术C main()
int a[5],i;
for(i=0;i<5;i++)
scanf("%d",&a[i]);
for(i=4;i>=0;i--)
printf("%d ",a[i]);
getch();
追问

你是在逗我么。。。

本回答被提问者和网友采纳

以上是关于逆序数还原c语言 输入数组 2 0 1 0 0 输出原序数 3 1 4 2 5的主要内容,如果未能解决你的问题,请参考以下文章

将数组中的数逆序存放

如何将一个数组中的值按逆序排放

c程序,一个整型数组,输入一个数,怎样判断这个数是不是属于此数组,写出程序!

类的数据成员为数组,怎么样根据键盘输入的数据顺序建立对象?

C语言编程,编程实现怎样将一个数组逆序输出?

3. 编一程序,从键盘输入一个三位数,求出其逆序数并输出,例如输入123,输出321。