Rotate Array

来源:互联网 发布:网络电视调试 编辑:程序博客网 时间:2024/06/15 21:46

Leetcode中的array的rotate问题

  Leetcode当中有一系列的题目是关于array的,而关于array的问题中又有一些题目是关于array的“rotate”的操作的。准备写一个关于rotate的专题,将关于rotate的问题整理一下。
  闲言少叙,我们直接来看第一题。
  https://leetcode.com/problems/rotate-array/

原题

Rotate an array of n elements to the right by k steps.
For example, with n = 7 and k = 3, the array [1,2,3,4,5,6,7] is rotated to [5,6,7,1,2,3,4].
Hint:
Could you do it in-place with O(1) extra space?
翻译:将长度为n的数组向右旋转k步,比如n=7,k=3,那么数组 [1,2,3,4,5,6,7] 被旋转成[5,6,7,1,2,3,4]。
提示:
你能在O(1)的额外空间中解决这个问题吗。

问题分析

  看到这个问题的基本想法就是每次rotate一步,然后将rotate进行k次就OK了,O(1)也没有什么问题,但是很显然时间复杂度达到O(kn),效率太低啦。其实接下来想的问题就是是否可以仅仅使用swap操作,将元素和他应该到的位置进行swap。
  [1,2,3,4,5,6,7] 被旋转成[5,6,7,1,2,3,4],我将1放到4的位置,4放到7的位置,7放到3的位置,3放到6的位置,6放到2的位置,2放到5的位置,最后5放到1的位置,每次我只要计算出这个被替换掉的元素下一次应该到的位置就行了!看似很完美,额外空间复杂度O(1)。
  实现了一下发现一个问题,只有k%n和n互质的时候,这个方法才有效!
  比如数组为[1,2,3,4],k=2。第一次1换到3,然后3换到1,到了初始位置了,结束,但是数组为[3,2,1,4]。当n和k%n有公因子的时候,就会出现这种问题。这个问题可以这样解决,找到n和k%n的最大公因子c,然后对数组的前c个数进行上述的迭代替换操作。这种方法的时间复杂度是O(n)。
贴上代码供大家参考:

public void rotate(int[] nums, int k) {    if(nums.length == 0) return;    k = k%nums.length;    if(k < 1) return;    int gcd = divisor(nums.length,k);    for(int i = 0; i < gcd; i++)    {        int temp = nums[i];        int tempIndex = i;        while((tempIndex + k)%nums.length != i)        {            int theTemp = nums[(tempIndex + k)%nums.length];            nums[(tempIndex + k)%nums.length] = temp;            temp = theTemp;            tempIndex = (tempIndex + k)%nums.length;        }        nums[i] = temp;    }    return;}int divisor(int m,int n){     int temp;     while(m%n!=0){         temp=n;         n=m%n;         m=temp;     }     return n; }

当然咯,网上通用的做法是先reverse整个数组,然后对前k个和后面n-k个进行reverse,想法很好,但是值得注意的是相比我的方法,该方法可以让每个元素替换两次才到位的哟,其实它的时间复杂度是O(2n),但是这个方法省却了最大公约数的计算,也贴上代码供大家参考。

public void rotate(int[] nums, int k) {    if(nums.length == 0)    {        return;    }    k = k%nums.length;    reverse(nums,0,nums.length - 1);    reverse(nums,0, k - 1);    reverse(nums,k,nums.length - 1);    return;}public void reverse(int[] nums, int head, int end){    int temp;    while(end > head)    {        temp = nums[end];        nums[end] = nums[head];        nums[head] = temp;        ++head;        --end;    }    return;}

接下来,我们何妨看看链表的rotate操作,哈哈~~~
  
  

0 0
原创粉丝点击