LeetCode:Rotate Array - 循环平移数组

1、题目名称

Rotate Array(循环平移数组)

2、题目地址

https://leetcode.com/problems/rotate-array/

3、题目内容

英文:Rotate an array of n elements to the right by k steps.

中文:将一个长度为n的数组,向右平移k个单位

4、解题方法1

一个比较易于理解的方法是新开辟一个与原数组等长的数组,循环考察原数组的元素,将它们放到新数组中平移后的位置上,最后再将新数组上的元素赋回原数组。

一段可以AC的Java代码:

/**
 * 功能说明:LeetCode 189 - Rotate Array
 * 开发人员:Tsybius2014
 * 开发时间:2015年8月9日
 */
public class Solution {
    
    /**
     * 数组平移
     * @param nums 数组
     * @param k 平移距离
     */
    public void rotate(int[] nums, int k) {
        
        int[] tempArray = new int[nums.length];
        k %= nums.length;
        
        //平移后的结果赋值到新数组
        for (int i = 0; i < nums.length; i++) {
            int j = (i - k) % nums.length;
            if (j < 0) {
                j += nums.length;
            }
            tempArray[i] = nums[j];
        }
        //将结果赋值回原数组
        for (int i = 0; i < nums.length; i++) {
            nums[i] = tempArray[i];
        }
    }
}

这个做法的缺点就是需要申请一个与传入数组等长的数组,当传入数组长度较长时,新申请的数组长度也很大。因此可以考虑一个不新申请数组的做法。

5、解题方法2

先考虑数组nums的长度与k互质的情况。假设nums是一个长度为7的数组,k的值是3,那么只需要6次交换就可以完成数组的移位了。各位置元素交换的次序见下图:

115612_9koD_1425762.png

每次交换,都把首个元素交换到它最终会出现的位置上,而每次交换后数组的首个元素,它最后会出现的位置都距上一个元素交换到的位置向右相差k(如果超过数组长度则从数组首元素重新计数)。

再考虑nums的长度不与k互质的情况,这个时候就需要求出nums的长度与k的最大公约数g,并将原数组分为g组,每组中的元素个数与k是互质的,分组进行上面的替换。

一段实现该算法的Java代码如下:

/**
 * 功能说明:LeetCode 189 - Rotate Array
 * 开发人员:Tsybius2014
 * 开发时间:2015年8月9日
 */
public class Solution {
    
    /**
     * 数组平移
     * @param nums 数组
     * @param k 平移距离
     */
    public void rotate(int[] nums, int k) {
        
        if (k == nums.length) {
            return;
        } 
        
        if (k > nums.length) {
            k %= nums.length;
        }
        
        int temp;
        int loops = gcd(nums.length, k);
        for (int i = 0; i < loops; i++) {
            for (int j = 1; j < nums.length / loops; j++) {
                temp = nums[i];
                nums[i] = nums[(i + k * j) % nums.length];
                nums[(i + k * j) % nums.length] = temp;
            }
        }
    }
    
    /**
     * 辗转相除法求最大公约数
     * @param a 正整数a
     * @param b 正整数b
     * @return 正整数a和b的最大公约数
     */
    public int gcd(int a, int b) {
        if (a == 0) {
            return b;
        }
        while (b != 0) {
            if (a > b) {
                a = a - b;
            } else {
                b = b - a;
            }
        }
        return a;
    }
}

END

转载于:https://my.oschina.net/Tsybius2014/blog/489726

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值