面试题:如何交换数组的两个部分

想了个很基础很实用的 机试题,面试的时候自己会出。
一个任意长度的数组,选取一个分割点,将数组分成前后两部分,交换前后两部分的数据。
要求:算法复杂度O(n)


这是标准答案:

void swap2parts(int *a,int len,int split){
    int *temp;
    int lenB = len-split;
    if(lenB<split){
        temp = (int *)malloc(split*sizeof(int));
        memcpy(temp,a,split*sizeof(int));
        memcpy(a,a+split,lenB*sizeof(int));
        memcpy(a+lenB,temp,split*sizeof(int));
    }else{
        temp = (int *)malloc(lenB*sizeof(int));
        memcpy(temp,a+split,lenB*sizeof(int));
        memcpy(a+len-split,a,split*sizeof(int));
        memcpy(a,temp,lenB*sizeof(int));
    }
    free(temp);
}

适合面试新手菜鸟

该题进阶的版本是:

交换两个数组部分,但是将空间复杂度限定在O(1),算法复杂度O(n)

可通过缩小问题范围的方式来求解

比如交换8和3两个长度的数组

0 1 2 3 4 5 6 7 | 8 9 10

可以将8按3份3份的分开

0 1 (2 3 4) (5 6 7)|( 8 9 10)

每次轮转一个位置

      —>
0 1 (8 3 4) (2 6 7)|( 5 9 10)

最后得到

0 1 (8  9 10) (2 3 4)|(5 6 7)

于是问题转化为

0 1|8 9 10

如此N次后得解

注意不要用递归来实现,用递归等于隐性的申请了O(n)的空间


再进一步,如果把设置数组值的次数限制在N步以内(N<=数组长度),这道题怎么做?

直觉上,我们相信,如果从第一个元素开始,将该元素直接放入到该元素的最终目的地,而目的地的值又去顶替目的地的目的地的值……如此下去,必然会遍历所有的元素,最后回到第一个元素,并完成交换,比如:

0 1 2 | 3 4

可按如下顺序遍历

0->3->1->4->2->0

注意步进长度只有3和-2两个值,正好是分割后数组的长度。

但也会有不能遍历完整的情况,比如12和8:

0->8->16->4->12->0

注意到这种情况中,两个数组长度存在大于1的最大公约数,因此先求出最大公约数m,再将该遍历走m遍即可。

上述两种解法源代码不给出,有兴趣的童鞋可以试试实现。如果你发现更少步骤更少空间能完成这个交换的方法欢迎提出。

转载于:https://my.oschina.net/ueharaai/blog/144414

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值