力扣面试经典算法150题:轮转数组

轮转数组

今天的题目是力扣面试经典150题中的数组的基础难度题:轮转数组。

题目链接:https://leetcode.cn/problems/rotate-array/description/?envType=study-plan-v2&envId=top-interview-150

问题描述

给定一个整型数组 nums 和一个整数 k,将数组中的元素向右轮转 k 个位置。

例如,给定数组 [1,2,3,4,5,6,7] 和 k = 3,轮转后的数组应该是 [5,6,7,1,2,3,4]。

  • 示例

    • 输入:
      nums = [1,2,3,4,5,6,7]
      k = 3
    • 输出:

      5,6,7,1,2,3,4

  • 示例:

    • 输入:
      nums = [-1,-100,3,99]
      k = 2
    • 输出:

      3,99,-1,-100

题目分析

题目要求能够将一个整型数组中的所有元素向右轮转 k 个位置。

先根据题目中的示例,理解一下轮转的含义。

观察示例可以发现,轮转意味着数组的最K个元素会按原有的顺序被移动到数组的最前面,而数组前面的元素则相应地向后移动。

解题思路

题目有多种解题思路,我们一个个来。

复制替换法

这个问题第一时间想到的方法是新建一个数组,将先将目标K个元素放入到新数组中,然后根据轮转的要求将原数组中的元素复制到新数组的正确位置上。最后将新数组的内容复制回原数组。这是方法一,我们叫它复制替换法。

在解答数组题目时,我们通常考虑不使用额外空间,也就是不新建数组的方式,所以我们再思考一下,怎么能在原数组上操作实现轮转。

反转数组法

轮转的意义是将后面K个元素放到前面,前面的元素放到后面,同时保证顺序不变。同时,我们不想操作额外的空间,就在原数组上操作。那么我们是不是可以先将整个数组反转,这个时候是不是相当于前面的元素放到了后面,后面的元素放到了前面,这个时候我们只需要考虑得到是,前k个元素需要按原来的位置摆放,后n-k个元素也按原来的位置摆放就行?

这两部分的元素如何恢复原有的顺序呢?还是反转,正所谓负负得正,我们反转得到的数组,再反转不就回到之前吗?

这样,先反转整体,在分别反转两部分的方法,我们叫它反转数组法,这是第二种方法。

实际算法代码

根据上面分析的两种方法,我们可以编写如下代码:

java 复制代码
public class Solution {


    public static void main(String[] args) {
        Solution solution = new Solution();
        int[] nums = {1, 2, 3, 4, 5, 6, 7};
        int k = 3;
        solution.rotate(nums, k);
        solution.rotate2(nums, k);
        for (int num : nums) {
            System.out.print(num + " ");
        }
    }


    public void rotate(int[] nums, int k) {
        int n = nums.length;
        k %= n; // 防止k大于数组长度的情况
        int[] result = new int[n];

        for (int i = 0; i < n; i++) {
            result[(i + k) % n] = nums[i];
        }
        for (int i = 0; i < n; i++) {
            nums[i] = result[i];
        }
    }


    public void rotate2(int[] nums, int k) {
        int n = nums.length;
        k %= n; // 处理 k 大于数组长度的情况
        reverse(nums, 0, n - 1); // 反转整个数组
        for (int num : nums) {
            System.out.print(num + " ");
        }
        System.out.println();
        reverse(nums, 0, k - 1); // 反转前 k 个元素
        for (int num : nums) {
            System.out.print(num + " ");
        }
        System.out.println();
        reverse(nums, k, n - 1); // 反转剩余的元素
        for (int num : nums) {
            System.out.print(num + " ");
        }
        System.out.println();
    }

    private void reverse(int[] nums, int start, int end) {
        while (start < end) {
            int temp = nums[start];
            nums[start] = nums[end];
            nums[end] = temp;
            start++;
            end--;
        }
    }

需要注意,两个函数不能同时调用,因为第一个函数过后,原数组已经被轮转了,第二个函数轮转的第一个轮转以后的数组。

结果

执行函数,测试通过:

图片是使用反转法输出,可以看到原数组被一步步反转成了目标数组。

提交到力扣,也正常通过:

总结

根据我们对函数的分析以及力扣提交后的结果,我们发现:

  1. 复制替换法使用了额外的空间,时间复杂度为 O(n),空间复杂度为 O(n)。这种方法简单易懂,适合初学者理解轮转的概念。
  2. 反转数组法在原地完成轮转操作,时间复杂度为 O(n),空间复杂度为 O(1)。这种方法虽然实现稍微复杂一点,但更节省空间。

力扣中还有最一个循环设置法,我没有想到,看了一下实现。简单的说就是一个个元素循环去放置。

这个方法比较复杂,但是一步步去debug观察元素的移动,可以很大程度上帮助新手理解数组的交换与移动,感兴趣的可以自己实现一下。

加油!!!

相关推荐
颜酱4 小时前
二叉树遍历思维实战
javascript·后端·算法
宝贝儿好4 小时前
第二章: 图像处理基本操作
算法
符哥20084 小时前
C++ 进阶知识点整理
java·开发语言·jvm
小陈phd4 小时前
多模态大模型学习笔记(二)——机器学习十大经典算法:一张表看懂分类 / 回归 / 聚类 / 降维
学习·算法·机器学习
@––––––4 小时前
力扣hot100—系列4-贪心算法
算法·leetcode·贪心算法
不想秃头的程序员4 小时前
Vue3 封装 Axios 实战:从基础到生产级,新手也能秒上手
前端·javascript·面试
Sayuanni%34 小时前
初阶_多线程1(线程含义与关键属性)
java
程序媛徐师姐4 小时前
Java基于微信小程序的模拟考试系统,附源码+文档说明
java·微信小程序·java模拟考试系统小程序·模拟考试微信小程序·模拟考试系统小程序·模拟考试小程序·java模拟考试小程序
CoovallyAIHub4 小时前
让本地知识引导AI追踪社区变迁,让AI真正理解社会现象
深度学习·算法·计算机视觉
CoderCodingNo4 小时前
【GESP】C++ 二级真题解析,[2025年12月]第一题环保能量球
开发语言·c++·算法