题目:一副从1到n的牌,每次从牌堆顶取一张放桌子上,再取一张放牌堆底,直到手上没牌,最后桌子上的牌是从1到n有序,设计程序,输入n,输出牌堆的顺序数组。(题目来源于一篇知乎上的文章)
思路:
在原牌堆a[n]以1到n的方式进行标记(即 a[0]=1,a[1]=2...),通过上述操作,产生新牌堆b[n]。若b[k]中的数值t+1,为原牌堆a[t]对应的位置,说明新牌堆第k+1张牌是原牌堆的第t+1张牌。由题意的,新牌堆第k+1张牌上的值为k+1,由此得原牌堆t+1张牌的值为k+1。a[t]=k+1。因为b[k]=t+1,所以a[b[k]-1]=b[k]。
为了保证空间更优,使用循环数组的方式,来实现在牌堆底加牌的步骤。
代码:
/*
* 一副从1到n的牌,每次从牌堆顶取一张放桌子上,再取一张放牌堆底,直到手机没牌,最后桌子上的牌是从1到n有序,设计程序,输入n,输出牌堆的顺序数组
*/
public class changeIndexAndValue{
public static void algorithm(int n)
{
int a[] = new int[n];
int b[] = new int[n];
int t=n-1;//新牌堆顶数组索引
int u=0;//原牌堆顶数组索引
int m=0;//原牌堆底数组索引,为了实现循环数组
for(int k=0;k<n;k++)//给每个原牌堆的牌打上标记
{
a[k]=k+1;
}
for(int l=0;l<n;l++) //共l个步骤
{
b[t]= a[u];//将当前原牌堆顶的牌放入新牌堆顶
t--;//新牌堆顶上移
a[m]=a[(u+1)%n];//将当前原牌堆顶的牌放入原牌堆底,利用循环数组,节省空间。
m++;
u=(u+2)%n;
}
for(int h=0;h<n;h++)//按顺序输出新牌堆里,原牌堆的标记,同时计算出原牌堆对应的数值
{
System.out.print(b[h]);
a[b[h]-1]= h+1;
}
System.out.println();
for(int p=0;p<n;p++)
{
System.out.print(a[p]);
}
}
public static void main(String[] args) {
changeIndexAndValue.algorithm(5);
}
}