关闭

编程之美---数组循环移位

标签: 编程之美
189人阅读 评论(0) 收藏 举报
分类:

设计一个算法,把一个含有N个元素的数组循环右移K位,要求时间复杂度为 O(N), 且只允许使用两个附加变量。

解法一:

简单的办法是,每次将数组中的元素右移一位,循环K次。abcd1234 -> 4abcd123 -> 34abcd12。

代码如下:

public static void rightShift(int[] array, int len, int k){
        while(k > 0){
            int temp = array[len-1];
            for(int i = len-1; i > 0; i--){
                array[i] = array[i-1];
            }
            array[0] = temp;
            k--;
        }
    }

算法的时间复杂度为 O(K*N)。
当K是一个远大于N的数时,上面的解法就需要改进了。当 k=50000000时,移位所需要的时间如下:
这里写图片描述

解法二:

观察循环右移的特点后,发现每个元素右移N位后,都会回到原来的位置,因此右移 K 位跟右移 k%N 位的结果是一样的,算法改进如下:

public static void rightShift(int[] array, int len, int k){
        k %= len;
        while(k > 0){
            int temp = array[len-1];
            for(int i = len-1; i > 0; i--){
                array[i] = array[i-1];
            }
            array[0] = temp;
            k--;
        }
    }

解法三:

假设原数组为12345678,循环右移4位后变为56781234。其中 5678 和 1234的顺序是不变的,可以将这两段当做整体,右移K位就是将这两段的顺序交换。

  1. 逆序排列 1234: 12345678 -> 43215678
  2. 逆序排列 5678: 43215678 -> 43218765;
  3. 整体逆序: 43218765 -> 56781234。

代码如下:

public static void reverse(int[] array, int start, int end){
        for(; start < end; start++, end--){
            int temp = array[end];
            array[end] = array[start];
            array[start] = temp;
        }
    }

    public static void rightShift(int[] array, int len, int k){
        k %= len;
        reverse(array, 0, len-k-1);
        reverse(array, len-k, len-1);
        reverse(array, 0, len-1);
    }

当k=50000000时,所花时间如下:
这里写图片描述

可以看到效率有了明显提升。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:19422次
    • 积分:514
    • 等级:
    • 排名:千里之外
    • 原创:28篇
    • 转载:3篇
    • 译文:5篇
    • 评论:4条
    博客专栏
    最新评论