编程题
编程实现:一个数组a中有N个整数,将数组中的元素向右移动m个位置,其中m是非负数
示例
输入
8 4(N=8,m=4)
4 3 2 1 5 6 7 8
输出
5 6 7 8 4 3 2 1
方法一:取余,逐个输出
#include <stdio.h>
int main()
{
int a[100],n,m,i;
scanf("%d %d",&n,&m);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
m=m%n; //防止m>n导致后面取余出错
for(i=0;i<n;i++)
{
printf("%d",a[(n+i-m)%n]);
if(i<n-1)
printf(" ");
}
return 0;
}
方法二:暴力求解,旋转m次,每次向后移动一位
【时间复杂度:O(N*m) 空间复杂度:O(1)】
#include <stdio.h>
int main()
{
int a[100],n,m,i,t,j;
scanf("%d %d",&n,&m);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
for(i=0;i<m;i++)
{
t=a[n-1];
for(j=n-1;j>0;j--)
{
a[j]=a[j-1];
}
a[j]=t;
}
for(i=0;i<n;i++)
printf("%d ",a[i]);
return 0;
}
方法三:开辟额外空间,以空间换时间(与方法一类似) b[i]=a[(n+i-m)%n];
【时间复杂度:O(N) 空间复杂度:O(N)】
#include <stdio.h>
int main()
{
int a[100],n,m,i,t,j;
scanf("%d %d",&n,&m);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
int b[100];
m=m%n;
for(i=0;i<n;i++)
{
b[i]=a[(n+i-m)%n];
}
for(i=0;i<n;i++)
printf("%d ",b[i]);
return 0;
}
方法四:(最优解)
4 3 2 1 5 6 7 8
前n-m个逆置:1 2 3 4 | 5 6 7 8
后m个逆置:1 2 3 4 | 8 7 6 5
整体逆置:5 6 7 8 4 3 2 1
【时间复杂度:O(N) 空间复杂度:O(1)】
#include <stdio.h>
void reverse(int a[],int left,int right)
{
while(left<right)
{
int t=a[left];
a[left]=a[right];
a[right]=t;
left++;right--;
}
}
int main()
{
int a[100],n,m,i,t,j;
scanf("%d %d",&n,&m);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
//前n-m个逆置
reverse(a,0,n-m-1);
//后m个逆置
reverse(a,n-m,n-1);
//整体逆置
reverse(a,0,n-1);
for(i=0;i<n;i++)
printf("%d ",a[i]);
return 0;
}