【每日一题】LeetCode 189. 旋转数组

题目详情

题目描述

给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。

示例 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]

说明

要求使用空间复杂度为O(1)的原地算法

题解

🙋‍♂️今日打卡~~

思路

拿到这道题,第一看过去,第一个想法是使用额外的空间,新申请一个一维数组用于保存当前需要移动的后半段元素,等待前半段元素在原始数组中移动到相应的位置之后,再把新数组的后半段元素移动到原数组的前半段。

题目下面的说明说是要求使用原地算法,就是不使用额外的空间。那就需要在原数组上下功夫,怎么才能让后半段元素变到前半段,前半段的元素变到后半段,确实需要想一想。想了一会,终于想通了,我们可以先把整个数组翻转,这样后半段元素已经变到前面了,只是后半段元素的位置是反的,还需要将翻转后的数组按照[0,k]和[k+1,n]翻转一次,这样就可以得到结果。

步骤

第一步,[0,n-1]数组长度整体翻转

第二步,[0,k-1]长度翻转

第三步,[k,n-1]长度翻转

注意

  • K需要对数组长度进行取余,可以减少不必要的操作。

代码

class Solution {
    public void rotate(int[] nums, int k) {
        int n = nums.length;
        k%=n;
        if(k==0){
            return;
        }
        reverse(nums,0,n-1);
        reverse(nums,0,k-1);
        reverse(nums,k,n-1);
    }
    private void reverse(int[] nums,int l,int r){
        while(l<r){
            int tmp = nums[l];
            nums[l] = nums[r];
            nums[r] = tmp;
            l++;
            r--;
        }
    }
}

总结

面对数组类型的题目,其实简单方法大部分人都可以想出来,只不过会有高时间复杂度,或者高空间复杂度,如果要优化,就需要认真思考。但是如果没有想出来最优解也不要太难受,因为有些东西是需要学习的,或者换句话说,需要看别人的题解,就好像是知识一样,没学过,不了解,很正常,我们只有见多了,看多了,把看过的吸收成自己的,这样才能提升自己。有做不错来的题,去把题解吃透吧。

写在后面

今天在疯狂循环播放《烟火里的尘埃》,不知道为什么我听这首歌的时候,并不会感觉到悲伤,而是感觉到一种气势磅礴,网抑云时间到了,“笑的开怀,哭的坦率,为何表情要让这世界安排”。还有就是最后那假音高音感觉确实像是腾空的烟火🎆,到最高点炸开。其实我之前是没有怎么听过他的歌的,只知道他是快乐男声出来的,纯路人,听完这首歌之后,感觉他还是很有能力的,小伙伴们可以去听听。

各位客官,走过路过,点个赞再走吧,感谢🙏
关注即可提高学习效率,关注不迷路

全部评论

相关推荐

1 收藏 评论
分享
牛客网
牛客企业服务