旋转阵列

2010年10月12日

今天的练习很简单但很棘手:编写一个函数来旋转数组的元素。该函数有两个参数:要旋转的数组和要旋转的元素数,其中正计数向左旋转,负计数向右旋转。例如,给定数组[1 2 3 4 5 6],向左旋转2将得到[3 4 5 6 1 2],再向右旋转2将恢复原始数组。

您应该确保正确处理边缘情况。如果计数为零或数组的长度,则数组应保持不变。如果计数大于数组的长度,您仍然应该做正确的事情;例如,在上面给出的数组上旋转8得到[3 4 5 6 12],与旋转2相同。

您的任务是编写上述旋转函数。完成后,欢迎您阅读运行建议的解决方案,或在下面的评论中发布自己的解决方案或讨论练习。

页:1 2

23对“旋转数组”的响应

  1. […]今天的编程实践练习,我们的目标是编写一个函数,将数组旋转到选定的数字[…]

  2. 雷姆科·尼梅耶

    My Haskell解决方案(请参阅http://bonsaicode.wordpress.com/2010/10/12/programming-praxis-rotate-an-array/对于带有注释的版本):

    旋转::Int->[a]->[a]旋转_[]=[]旋转n xs=b++a,其中(a,b)=splitAt(mod n$length xs)xs

    值得注意的是,给定的Scheme解决方案在长度为0的数组上失败。

  3. 格雷厄姆

    Python解决方案,类似于Remco的Haskell的逻辑:

    def-rotate(数组,nelts):n=nelts%len(数组)返回数组[n:]+数组[:n]
  4. 满意的

    这里是我的解决方案在F#中。由于模运算符的定义方式,必须做一些额外的工作。

  5. http://pastebin.com/5wKvVgWG

    使用n个交换进行就地轮换,并尝试具有相当好的局部性。

  6. 阿比

    阿勒·拉科特。这是我第一次使用多个返回值。

    #朗球拍
    (需要(仅在rnrs/base-6 mod中)

    (定义(旋转a-vector rot)
    (如果(<=(向量长度a-向量)1)
    a-矢量
    (带值的调用
    (λ ()
    (矢量-拆分-a矢量(mod-rot(矢量长度-a矢量))
    (λ(1/2)
    (矢量-追加第二个第一个)))

  7. Axio公司

    ;;口齿不清
    ;;返回原始数组,而不是像这样的循环列表块
    ;;“rot l n=take(length l)$drop(如果(n>0),则n else(abs((length l)-n))$cycle l”
    (拆卸旋转(arr n)
    (let*((arlen(长度arr))
    (new-arr(make-array arlen))
    (阿伦下方的i循环

    (setf(aref new-arr i)(aref arr(mod(+i n)arlen))
    (阿伦下方的i循环

    (setf(aref arr i)(aref new-arr i)))

  8. 吉姆·里斯

    ;;简单、防弹。

    (定义(反向范围!v开始-结束)
    (do((i开始(+i 1)))
    (j(-端1)(-j 1))
    ((>=i j)v)
    (let((tmp(矢量参考v i)))
    (矢量集!v i(矢量参考v j))
    (向量集!v j tmp)))

    (定义(矢量旋转!v n)
    (let((N(向量长度v)))
    (除非(零?N)
    (let((n(模n n)))
    (反向范围!v 0 n)
    (反向范围!v n n)
    (反向范围!v 0 N))
    v) )

  9. 莱安德罗·帕切科

    使用python列表理解:

    定义rotate_array(arr,旋转):
    对于范围(len(arr))中的i,返回[arr[(旋转+i)%len(arr)]

  10. 拉尔斯·比约恩福特

    这是一个Java版本。没有递归,只有一个普通循环。
    不是最短的解决方案,但它可以处理所有边缘情况
    (包括比数组大小更大的左旋转)。

    public int[]rotate(int[]数组,int计数){int length=数组长度;if(长度==0||count%长度==0)返回数组;计数=((计数%长度)+长度)%长度;//限制并使其为正int[]dest=新int[length];for(int i=0;i<长度;i++){int index=(i+count)%长度;dest[index]=数组[i];}返回dest;}
  11. 诺兹克斯

    ;;口齿不清
    (取消循环(第一个参数)
    (第二
    ((空lst)lst)
    ((=(mod arg(长度lst))0)lst)
    (t(旋转(nconc(cdr lst)(列表(车辆lst)))(-arg 1)))

  12. 氙气

    这里的关键是不要使用预先准备好的旋转功能。以下是我在Python中的解决方案:

    def旋转器(arrayOld,rotateValue):
    arrayLength=arrayOld__透镜_()
    while rotateValue>arrayLength:rotateValue-=arrayLongth
    当rotateValue为0时:
    对于范围内的i(arrayLength):
    如果i<rotateValue:arrayNew_buffer.append(arrayOld[i])
    else:arrayNew.append(arrayOld[i])
    其他:
    对于范围内的i(arrayLength):
    如果i<(arrayLength+rotateValue):arrayNew_buffer.append(array旧[i])
    else:arrayNew.append(arrayOld[i])
    对于数组中的i New_buffer:arrayNew.append(i)
    返回阵列新建

  13. 斯巴尼尔·戈帕德

    /*这是我的C实现*/

    #包括
    #包括

    int*rotate(int*a,int大小,int计数)
    {

    int*c,j,temp,k=0,符号;

    c=(int*)calloc(size,sizeof(int));

    符号=计数>>31;

    温度=(符号==-0x01)?(size-(-count)):计数;

    对于(j=(温度);j<尺寸;j++)
    {
    c[k]=a[j];
    k++;
    }

    对于(j=0;j<(温度);j++)
    {
    c[k]=a[j];
    k++;}

    a=c;

    返回a;
    }

    整型main()
    {
    int*b,cnt,大小,i;

    printf(“输入数组大小?”);
    扫描(“%d”,&size);

    b=(int*)calloc(size,sizeof(int));
    对于(i=0;i<大小;i++)
    扫描(“%d”,&b[i]);

    而(1)
    {
    printf(“要旋转的元素数?\n\t\t向左旋转的正值\n\t\t向右旋转的负数\n\t\t输入“0”退出”);
    扫描(“%d”,&cnt);
    如果(cnt==0)
    {
    退出(0);
    }
    其他{
    cnt=cnt%尺寸;
    b=旋转(b,尺寸,cnt);
    printf(“旋转数组\n”);
    对于(i=0;i<大小;i++)
    printf(“\t%d”,b[i]);
    }

    }
    返回0;
    }

  14. 斯巴尼尔·戈帕德

    #包括
    #包括

    int*rotate(int*a,int大小,int计数)
    {

    int*c,j,temp,k=0,符号;

    c=(int*)calloc(size,sizeof(int));

    符号=计数>>31;

    温度=(符号==-0x01)?(size-(-count)):计数;

    对于(j=(温度);j<尺寸;j++)
    {
    c[k]=a[j];
    k++;
    }

    对于(j=0;j<(温度);j++)
    {
    c[k]=a[j];
    k++;}

    a=c;

    返回a;
    }

    整型main()
    {
    int*b,cnt,大小,i;

    printf(“输入数组大小?”);
    扫描(“%d”,&size);

    b=(int*)calloc(size,sizeof(int));
    对于(i=0;i<大小;i++)
    扫描(“%d”,&b[i]);

    而(1)
    {
    printf(“要旋转的元素数?\n\t\t向左旋转的正值\n\t\t向右旋转的负数\n\t\t输入“0”退出”);
    扫描(“%d”,&cnt);
    如果(cnt==0)
    {
    退出(0);
    }
    其他{
    cnt=cnt%尺寸;
    b=旋转(b,尺寸,cnt);
    printf(“旋转数组\n”);
    对于(i=0;i<大小;i++)
    printf(“\t%d”,b[i]);
    }

    }
    返回0;
    }

  15. 拉利特·莫汉

    我的python解决方案:
    网址:http://codepad.org/nKk5LOLl

  16. 奇尔·特拉利

    你们太棒了,我从你们的解决方案中学到了很多!

    下面是我的emacs lisp实现(使用列表保存数组):

    (化解债务8r(an))
    (如果
    (=0(长度a))

    (项目
    (追加
    (nthcdr(mod n(长度a))a)
    (但是最后一个a(-(长度a)(abs(mod n(长度a)))))
    ))))

  17. […]编程实践,旋转数组。我认为它更像是一种补偿。将数组内容移位±x个空格。公共静态[…]

  18. 骑士

    这是我的C#。

    静态void RotateArrayInplace<T>(T[]数组,int计数){count%=数组。长度;如果(计数==0)回报;else if(计数<0)count+=数组。长度;T[]tmp=新T[count];数组。复制(数组、tmp、计数);数组。复制(数组,计数,数组,0,数组。长度-计数);数组。复制(tmp,0,array,array.Length-count,count);}静态T[]RotateArray(T[]数组,int计数){count%=数组。长度;如果(计数==0)return(T[])数组。克隆();else if(计数<0)count+=数组。长度;T[]结果=新的T[array.Length];数组。复制(数组,0,结果,数组。长度-计数,计数);数组。复制(数组,计数,结果,0,数组。长度-计数);返回结果;}
  19. 杰布

    用C语言完成,将数组旋转到位,而不是返回一个新数组。我的解决方案中的实际旋转涉及(n+gcd(n,offset))赋值,不使用单个临时变量的额外内存设备。如果n和offset是互质的,我们可以单次旋转数组;如果没有,我们需要将其分解为gcd(n,offset)子问题。

    void rotate(int*数组,int len,int偏移量){int i,j,gcd,tmp;while(偏移<0)偏移量+=长度;gcd=_gcd(偏移量,长度);对于(j=0;j<gcd;j++){tmp=数组[offset%len+j];对于(i=len/gcd;i>1;i--)数组[(i+1)*offset%len+j]=数组[i*offset%len+j];数组[2*offset%len+j]=tmp;}}

    (_gcd函数是我们为2010年1月15日的练习编写的函数)

    我发现代码很难理解,不知道如何使它更容易阅读。为了帮助澄清一点,以下是将长度为9的数组旋转偏移量为5时发生的情况:
    5->tmp
    0 -> 5
    4 -> 0
    8 -> 4
    3 -> 8
    7->3
    2 -> 7
    6 -> 2
    1 -> 6
    tmp->1

    同一数组偏移6:
    6->tmp
    0 -> 6
    3 -> 0
    tmp->3
    7->tmp
    1->7
    4 -> 1
    tmp->4
    8->tmp
    2->8
    5 -> 2
    tmp->5

  20. 哈希1aby

    这可以通过恒定的空间成本来实现,因为偏移平移=原点处的反射,然后是(原点+偏移)处的反射。反射可以通过就地成对交换元素来实现。

  21. 阿蒂夫·法鲁克

    你好,我是新来的
    //_________________________________________________________//

    #包括

    使用命名空间标准;

    //_________________________________________________________//

    //确定绝对值和计算极端值的功能

    int AbsolShiftfunc(int用户,int ArrSize)

    {

    int Absolshift;

    int ShiftType;

    if(用户>=0)

    {

    Absolshift=用户;

    ShiftType=1;

    if(UserArrSize)

    {

    while(Absolshift>ArrSize)

    {

    Absolshift=Absolshift–ArrSize;

    }

    }

    }

    else if(用户<=0)

    {

    Absolshift=-用户;

    ShiftType=0;

    if(-用户ArrSize)

    {
    while(Absolshift>ArrSize)

    {

    Absolshift=Absolshift–ArrSize;

    }

    }

    }

    if(ShiftType==1)

    {

    return Absolshift;

    }

    else if(ShiftType==0)

    {

    return——绝对位移;

    }

    }

    //_________________________________________________________//

    int IndivShiftfunc(int初始值,int Absolshift,int ArrSize)

    {

    int Destinatex=初始+(Absolshift);

    if(目标索引>=ArrSize)

    {
    while(目标索引>=ArrSize)

    {

    Destinex=Destinex–ArrSize;

    }

    }

    如果(Destindex<0)

    {
    while(目标索引ArrSize)

    {

    目标索引=目标索引+ArrSize;

    }

    }

    return目的地索引;

    }

    //_______________________________________________________//

    无效解决方案()

    {

    //声明任意原始数组和副本

    常量int大小=700;

    int ArrO[size];

    int ArrC[size];

    int Arrsize=0;

    //换档前的培训

    int Usershift;

    int AbsoluteShift;

    int目的地索引;

    //生命周期价值
    const int Sentinel=-999;

    //要求用户指定值并计算查询数组大小

    cout<<“\n\n\n\n\n”;

    cout<<“\t旋转数组\n\n\n”;

    cout<<“\t____________________________________________________________ \n\n\n”;

    cout<<“\t请指定要旋转的数组。\n\n\t在数组末尾输入-999。\n\n”;

    cout<>ArrO[Arrsize],cout<<“\n”;

    while(ArrO[Arrsize]!=哨兵)

    {

    Arrsize++;

    cout<>ArrO[Arrsize],cout<<“\n”;

    }

    cout<>用户移位,cout<<“\n”;

    //计算绝对偏移

    AbsoluteShift=AbsolShiftfunc(Usershift,Arrsize);

    //计算移位

    for(int Counter=0;Counter<Arrsize;Counter++)

    {

    Destinationindex=IndivShiftfunc(计数器、AbsoluteShift、Arrsize);

    ArrC[Destinationindex]=ArrO[Counter];

    }

    //显示原始阵列和旋转阵列

    cout<<“\t*原始数组:_\n\n\t”;

    cout<<“\t\t[”;

    for(int Counter=0;Counter<Arrsize;Counter++)

    {

    cout<<ArrO[Counter]<<“,”;

    }

    cout<<“]\n\n”;

    cout<<“\t*旋转数组:_\n\n\t”;

    cout<<“\t\t[”;

    for(int Counter=0;Counter<Arrsize;Counter++)

    {

    cout<<ArrC[Counter]<<“,”;

    }

    cout<<“]\n\n”;

    cout<<“\t____________________________________________________________ \n\n\n\t”;

    }
    //_________________________________________________________//

    空main()

    {

    解决方案();

    }

    //_________________________________________________________//

    附言:我是个乞丐,所以请不要打我

  22. […]“块交换”算法。Bentley还讨论了第三种算法,他称之为“反转”算法,这是我们几年前实现的。宾利接着进行了时间比较[…]

留下评论