要求:1---1000000 中由于想11,22,..,110,101,..这类数都被去除掉了。所以只剩下:1,2,3,...,10,12,..21,23...等等,要求输入一个数x,即找x位置对于去除后的集合中的哪儿元素;
思路:由于是数据多,如果根据传统思想进行暴力对于每个数据进行处理后让后进行定位查找就效率太低了:因为要对每个数进行判断其中有没有重复的数据如125033000要变量过程,然后进行存数据,再定位查找;
所以:利用树的概念,树的层变量,但又不是真的遍历只是在输入x是判断它是哪一层的,然后对剩下的数据进行这层数据的定位,定位是用到树的逆推,从而推出它经过的路径这样其路径就是它定位的数;
![](https://i-blog.csdnimg.cn/blog_migrate/619f87895d8e6b96f36fcdd590bab916.jpeg)
算法思想:C语言
#include
#define N 10
void main(){
int n[10]={0,1,2,3,4,5,6,7,8,9};//用来记录一组0--9的数用来进行输出结果用的
int tree[N][2];//用来保持树状态的一个表格如:第二层对应tree[0][],有tree[0][0]=9个分支,一共有tree[0][1]=9*9个元素;
int x,i,j,m;
while(scanf("%d",&x)!= EOF){
//用来初始化数的状态表
for(i=0;i
for(i=9,j=0;j
if(i==9){
tree[j][0]=i;
tree[j][1]=tree[j][0];
j++;
}
tree[j][0]=i;
tree[j][1]=tree[j][0]*tree[j-1][1];
j++;
}
//根据输入的sum来进行它是在哪一层的判断;如输入sum=1000,那么他的i=3即3+2=5在第5层;
//下面的例子默认是以输入1000进行运算的分析
int sum=0;
for(i=0;i<10;i++){
sum+=tree[i][1];
if(sum>x)
break;
}
//对剩下的元素如262个在第5层的那个位置进行判断;
x-=(sum-tree[i][1]);
for(j=0;j<=i;j++){//结果一共有几个数,也即是要经过树的路径个数;这里是4次
//假如把其按照第二次的子数的个数进行分组即9组那么对于第5层中的元素4536个每组要有多少个元素,然后利用x进行
//相除的到它是在落在第二层的那个分组;如(262/(4536/9))=1落在第二层的第一个节点上
int temp=x/(tree[i][1]/tree[j][1]);
//主要是为了进行除数的结果进行向上取值如:5/3我们要的结果是2 0/(4536/9)应该为1即为第一组 0/3=0也是整除所以有||temp==0进行加慝temp++;
if(x%(tree[i][1]/tree[j][1])!=0||temp==0)
temp++;
temp=temp%tree[j][0];
//当整除时其实是组中的最后一个元素;
if(temp==0)
temp=tree[j][0];
//printf("%d---",temp);
//进行对于输出的n[]数值进行变量找temp个对于n[]中的是哪个数值
//值得注意的是一个组中元素是根据其父节点来决定的如:父节点走的是:0--1--5 那么第4层对应的组只能有0,2,3,4,6,7,8,9由于最高位的0不算,所以这里还是有0
//这时把n[]={0,,-1,2,3,4,-1,6,7,8,9}用-1来标记父节点已经用过这个数了。
for(m=0;m
if(n[m]!=-1)
temp--;
if(temp==0){//找到要输出的数了
if(j==0) m++;
printf("%d",n[m]); //输出结果
n[m]=-1;//标记
break;
}
}
}
printf("\n");
}
}