当前位置: 首页 > news >正文

力扣面试经典算法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个元素也按原来的位置摆放就行?

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

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

实际算法代码

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

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观察元素的移动,可以很大程度上帮助新手理解数组的交换与移动,感兴趣的可以自己实现一下。

加油!!!


http://www.mrgr.cn/news/960.html

相关文章:

  • 如何保证Redis缓存和数据库的数据一致性
  • 简易双端视频通信实现
  • 16.FreeRTOS内存管理
  • 基于SpringBoot的论坛系统设计与实现(源码+lw+部署文档+讲解等)
  • 正则表达式入门:Python ‘ re ‘ 模块详解
  • TCP/IP 协议及其协议号
  • Java-HttpURLConnection 从服务器获取输入流和使用RestTemplate来获取输入流。
  • 一个简单的WEB开发案例
  • 7.实时时钟(RTC)
  • 深入解析CDN(内容分发网络):架构、优势与实现
  • 微分方程(Blanchard Differential Equations 4th)中文版Section3.2
  • ansible
  • SQL - 汇总与分组
  • 机器学习(3)-- 一元线性回归
  • Linux内核(5)——从udev/mdev工作原理到亲手实现SD卡热插拔
  • CentOS7下制作openssl1.1.1i RPM包并升级
  • BUUCTF PWN wp--warmup_csaw_2016
  • MySQL面试相关精选
  • Github 2024-08-19 开源项目周报Top15
  • jenkins workpase优化清理