Leetcode189. 旋转数组

本文提供三种解决LeetCode 189旋转数组问题的方法:使用额外数组、环状替换和反转。详细解析了每种方法的原理、步骤及优缺点,附带Scala代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Leetcode189. 旋转数组

题目:
给定一个数组,将数组中的元素向右移动 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]

题解:

方法一:
使用额外的数组
我们可以用一个额外的数组来将每个元素放到正确的位置上,也就是原本数组里下标为 iii 的我们把它放到 (i+k)%数组长度(i+k)\%数组长度(i+k)% 的位置。然后把新的数组拷贝到原数组中。
scala代码如下:

def rotate(nums: Array[Int], k: Int): Unit = {
    val arr = new Array[Int](nums.length)
    for (i <- 0 until nums.length) {
      arr((i + k) % nums.length) = nums(i)
    }
    for (i <- 0 until nums.length) {
      nums(i) = arr(i)
    }
  }

方法二:
使用环状替换
如果我们直接把每一个数字放到它最后的位置,但这样的后果是遗失原来的元素。因此,我们需要把被替换的数字保存在变量 temp 里面。然后,我们将被替换数 temp 放到它正确的位置,并继续这个过程 n 次, n 是数组的长度。这是因为我们需要将数组里所有的元素都移动。但是,这种方法可能会有个问题,如果 n%k==0,其中 k=k%n (因为如果 k 大于 n ,移动 k 次实际上相当于移动 k%n 次。这种情况下,我们会发现在没有遍历所有数字的情况下回到出发数字。此时,我们应该从下一个数字开始再重复相同的过程。

现在,我们看看上面方法的证明。假设,数组里我们有 n个元素并且 k 是要求移动的次数。更进一步,n%k=0 。第一轮中,所有移动数字的下标 i满足 i%k == 0 。这是因为我们每跳 k 步,我们只会到达相距为 k 个位置下标的数。每一轮,我们都会移动 n/k 个元素。下一轮中,我们会移动满足 i%k == 1 的位置的数。这样的轮次会一直持续到我们再次遇到 i%k==0 的地方为止,此时 i=k 。此时在正确位置上的数字共有 k * k/n = n 个。因此所有数字都在正确位置上。

让我们看一下接下来的例子,以更好地说明这个过程:
在这xxx里插入图片描述
scala代码如下:

def rotate2(nums: Array[Int], k: Int): Unit = {
    var k1 = k
    k1 = k1 % nums.length
    var count = 0
    var start = 0

    while (count < nums.length) {
      var current = start
      var pre = nums(start)
      do {
        val next = (current + k1) % nums.length
        val temp = nums(next)
        nums(next) = pre
        pre = temp
        current = next
        count = count + 1
      } while (start != current)
      start = start + 1
    }
  }

方法三:
反转
例:输入: [1,2,3,4,5,6,7] 和 k = 3
原始数组 : 1 2 3 4 5 6 7
反转所有数字后 : 7 6 5 4 3 2 1
反转前 k 个数字后 : 5 6 7 4 3 2 1
反转后 n-k 个数字后: 5 6 7 1 2 3 4 --> 结果
scala代码如下:

def rotate3(nums: Array[Int], k: Int): Unit = {
    var k1 = k
    k1 = k1 % nums.length
    reverse(nums, 0, nums.length - 1)
    reverse(nums, 0, k1 - 1)
    reverse(nums, k1, nums.length - 1)
  }

  def reverse(nums: Array[Int], start: Int, end: Int): Unit = {
    var start1 = start
    var end1 = end
    while (start1 < end1) {
      val temp = nums(start1)
      nums(start1) = nums(end1)
      nums(end1) = temp
      start1 = start1 + 1
      end1 = end1 - 1
    }
  }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值