您的位置:首页 > 编程语言

《编程珠玑》第二章-循环移位

2010-11-08 11:20 295 查看
问题:将一个n维向量向左循环移位m位。如向量0,1,2,3,4,5,6,7,8,9向左循环移位3位,结果是3,4,5,6,7,8,9,0,1,2。

方法1:每次循环移位1位,执行m次。辅助空间1,时间复杂度O(n*m)

方法2:用m维的辅助空间暂存前m个元素,对剩下的n-m个元素进行移位,最后将m个元素移动向量末尾。辅助空间m,时间复杂度O(n)。

//方法1
int temp;
for(int i=0; i<m; i++)
{
temp = a[0];
for(int j=0; j<n-1; j++)
a[j]=a[j+1];
a[n-1] = temp;
}
//方法2
int t[m];
for(int i=0; i<m; i++)
t[i] = a[i];
for(int i=0; i<n-m; i++)
a[i] = a[i+m];
for(int i=0; i<m; i++)
a[n-m+i] = t[i];


方法3:(杂技方法)先a[0]-->temp,然后a[i]-->a[0],a[2i]-->a[i],直到遇到a[0],将temp-->刚才移动的最后一个位置。如

果没有移动完则a[i]-->temp,然后a[1+i]-->a[1],a[1+2i]-->a[1+i],循环,直到全部移动。辅助空间O(1),时间复杂度O(n).

int count = 0; //count等于n时移动完
int i = 0;
int j;
int temp;
while(1)
{
temp = a[i];
j = (i+m)%n;
while(j != i)
{
a[(j-m+n)%n] = a[j];
count++;
j = (j+m)%n;
}
a[(i-m+n)%n] = temp;
count++;
if(count<n)
i++;
else
break;
}


方法4:(求逆方法)利用了
(b,a)=(arbr)r,辅助空间1,时间复杂度O(n). 还可以扩展为(c,b,a)=(ar,br,cr)r噢~

void reverse(int *a, int b, int e)
{
int len = e-b+1;
int temp;
for(int i=0; i<len/2; i++)
{
temp = a[b+i];
a[b+i] = a[e-i];
a[e-i] = temp;
}
}
reverse(a,0,m-1);
reverse(a,m,n-1);
reverse(a,0,n-1);


方法5:(分块方法)对于向量(a,b),其中a是m维的,b是n-m维,将b分成两部分,b=(b1,b2),其中b2同a也是m维的,首先交换a和b2的位置。然后对(b2,b1)部分再循环进行上述操作。m>n-m时调换位置,继续。辅助空间O(1),时间复杂度O(n).

int p = m;
int i = m; //每次交换的块元素个数
int j = n-m; //每次交换的两个块的间隔
while(i != j)
{
if(i>j) //此时i和j的地位就要对调了
{
swap(a,p-i,p,j);
i -= j;
}
else
{
swap(a,p-i,p-i+j,i);
j -= i;
}
}
swap(a,p-i,p,i);
//swap函数将位p开始和位q开始的m个元素位置对调
void swap(int *a, int p, int q, int len)
{
int temp;
for(int i=0; i<len; i++)
{
temp = a[p+i];
a[p+i] = a[q+i];
a[q+i] = temp;
}
}


效率:分块>求逆>杂技
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: