LeetCode旋转数组

5 篇文章 0 订阅
3 篇文章 0 订阅

问题描述

        给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。尽可能想出更多的解决方案,至少有三种不同的方法可以解决这个问题。要求使用空间复杂度为 O(1) 的原地算法。

示例1
        输入: [1,2,3,4,5,6,7] 和 k = 3
        输出: [5,6,7,1,2,3,4]
        解释:
        向右旋转 1 步: [7,1,2,3,4,5,6]
        向右旋转 2 步: [6,7,1,2,3,4,5]
        向右旋转 3 步: [5,6,7,1,2,3,4]

示例2
        输入: [-1,-100,3,99] 和 k = 2
        输出: [3,99,-1,-100]
        解释:
        向右旋转 1 步: [99,-1,-100,3]
        向右旋转 2 步: [3,99,-1,-100]

解题思路

        这是一道比较常见的题,很多教材的课后习题中也有这道题目,第一次遇见这道题时我也是采用暴力算法,循环求解,看到翻转解法时很不能理解,不知道为什么别人能想出这样的算法,现在感觉多少有些了解了,尝试讲一下。
        数组右移k个位置,我们只看最后结果,就是数组最后的k位平移到了数组最前面的k位。数组最前面的(length-k)位向后平移k个位置。按照这样的想法,我们先将前面的(length-k)翻转,为最后一次翻转产生的逆序做提前的翻转,使之翻转后仍是原有顺序,第二个翻转也是这个道理。如果这样看的话,我们先执行一次全体翻转,在执行1,2步翻转也是一样的,只不过是翻转的起始位置发生了变化。翻转本省就带有位置的移动,这是十分重要的一点。

代码实现

public class TranslationArray {

    public static void main(String[] agrs){

        int[] nums = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        
        translationArray(nums, 6);
        
        for (int num : nums) {
            System.out.println(num);
        }
    }

    public static void translationArray(int[] nums, int k){
    	// 当k大于数组的长度时,避免产生数组下标越界
        k %= nums.length;
        // 当位移为空或者数组长度小于2时,不进行操作
        if(k == 0 || nums.length <= 1) return;
        // 翻转前(length - k)位
        reverse(nums, 0, nums.length - 1 - k);
        // 翻转后k位
        reverse(nums, nums.length - k, nums.length -1);
        // 翻转整个数组
        reverse(nums, 0, nums.length -1);
    }

    public static void reverse(int[] array, int start, int end){
        int temp, mid = (end - start) / 2;
        // 依次交换首位位置元素,向中间循环
        for(int i = 0; i <= mid; i++){
            temp = array[start + i];
            array[start + i] = array[end - i];
            array[end - i] = temp;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值