我想编写一个程序,根据用户的输入(正 - >,负&lt ;-)将数组向右或向左移动一定数量的位置。该程序必须具有O(n)复杂性。我是用这种方式写的,但它不能正常工作。在示例中,输出应为“2,3,4,5,6,1”,但在我的版本中为“6,2,3,4,5,1”。
#include <stdio.h>
#include <string.h>
#include <math.h>
void rotate(int *array, int N, int D);
int main(){
int i;
int array[] = {1, 2, 3, 4, 5, 6};
rotate(array, sizeof(array)/sizeof(int), 5);
for(i=0; i<sizeof(array)/sizeof(int); i++)
printf("%d\t", array[i]);
return 0;
}
void rotate(int *array, int N, int D){
int i, j, *tmp, d;
tmp = malloc(abs(D) * sizeof(int));
if(D<0){
d = abs(D);
for(i=d; i<N; i++){
tmp[i%d] = array[i];
array[i] = array[i-d];
array[i-d] = tmp[i%d];
}
}
if(D>0){
for(i=(N-D-1); i>=0; i--){
tmp[i%D] = array[i];
array[i] = array[i+D];
array[i+D] = tmp[i%D];
}
}
}
谢谢。
答案 0 :(得分:14)
旋转算法使用反转的函数
reverse()
数组的子序列。引自专栏:让我们将问题视为将数组
ab
转换为数组ba
,但我们也假设我们有一个可以反转的功能 数组的指定部分中的元素。从ab开始,我们 反转a得到a_r b,反转b得到a_r b_r,然后反转 得到的整个事情(a_r b_r)_r,这正是ba。
这就是你需要的。来自用户的输入定义了将数组分区为两个块A和B的位置。这是我的实现:
void reverse(int a[], int sz) {
int i, j;
for (i = 0, j = sz; i < j; i++, j--) {
int tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
}
void rotate(int array[], int size, int amt) {
if (amt < 0)
amt = size + amt;
reverse(array, size-amt-1);
reverse(array+size-amt, amt-1);
reverse(array, size-1);
}
我测试了它并且它正在工作。另外,请注意如何处理负旋转:将size
元素amt
数组向左旋转(即使用负值)与向右旋转size+amt
相同。
享受优雅的代码,不要忘记在评论中加入学分(当然是Jon Bentley)。
答案 1 :(得分:2)
正确旋转使用:
temp[0]=a[0];
for(i=1;i<=n;i++)
{
temp[i%2]=a[(i*d)%n];
a[(i*d)%n]=temp[(i+1)%2];
}
左旋转使用:
temp[0]=a[0];
for(i=1;i<=n;i++)
{
temp[i%2]=a[(i*(n-d))%n];
a[(i*(n-d))%n]=temp[(i+1)%2];
}
其中a [n]是数组,d是要旋转的位置数。
答案 2 :(得分:1)
你只是交换元素位置:位置1的元素放在位置6,反之亦然......你应该重写最后一部分。有两种方法:
答案 3 :(得分:0)
最简单的方法是旋转,但除此之外,为什么不尝试仅重新定位数组/列表的元素。
def circularArrayRotation(a, k):
k=k%len(a)
b=a[len(a)-k:len(a)]
#print(b)
a=b+a[0:len(a)-k]
print(a)
那是右旋,对于左旋只需翻转
b=a[k:len(a)] and a=b+a[0:k]