leetcode
leetcode 151 ~ 200
轮转数组

轮转数组

难度:

标签:

题目描述

给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。

 

示例 1:

输入: nums = [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:

输入:nums = [-1,-100,3,99], k = 2
输出:[3,99,-1,-100]
解释: 
向右轮转 1 步: [99,-1,-100,3]
向右轮转 2 步: [3,99,-1,-100]

 

提示:

  • 1 <= nums.length <= 105
  • -231 <= nums[i] <= 231 - 1
  • 0 <= k <= 105

 

进阶:

  • 尽可能想出更多的解决方案,至少有 三种 不同的方法可以解决这个问题。
  • 你可以使用空间复杂度为 O(1) 的 原地 算法解决这个问题吗?

代码结果

运行时间: 28 ms, 内存: 23.4 MB


/*
 * Problem: Given an array, rotate the array to the right by k steps, where k is non-negative.
 * Example 1:
 * Input: nums = [1,2,3,4,5,6,7], k = 3
 * Output: [5,6,7,1,2,3,4]
 * Example 2:
 * Input: nums = [-1,-100,3,99], k = 2
 * Output: [3,99,-1,-100]
 *
 * Approach using Java Streams:
 * 1. Normalize k to ensure it is within the bounds of the array length.
 * 2. Use streams to concatenate the two parts of the array that need to be swapped.
 */
 
import java.util.Arrays;
import java.util.stream.IntStream;
 
public class RotateArrayStream {
    public int[] rotate(int[] nums, int k) {
        int n = nums.length;
        k = k % n;
        return IntStream.concat(
                Arrays.stream(Arrays.copyOfRange(nums, n - k, n)),
                Arrays.stream(Arrays.copyOfRange(nums, 0, n - k))
        ).toArray();
    }
}
 

解释

方法:

这个题解的思路是直接切片。首先将 k 对数组长度取模,得到实际需要轮转的次数。然后将原数组切片为两部分:后 k 个元素 nums[-k:] 和除去后 k 个元素的部分 nums[:-k],再将这两部分拼接起来赋值给原数组,即可得到轮转后的结果。

时间复杂度:

O(n)

空间复杂度:

O(1)

代码细节讲解

🦆
在题解中提到`k = k % len(nums)`的操作是为了什么?如果不进行这一步操作,会出现什么问题?
这个操作是为了处理当旋转次数`k`大于数组长度的情况。取模操作确保了实际的旋转次数不会超过数组的长度,因此可以避免无效的多次全数组旋转,提高效率。如果不进行这一步操作,当`k`大于数组长度时,数组会进行多余的完整旋转,这不仅增加了计算量,而且是不必要的,因为每旋转一次数组长度,数组状态会恢复到原始状态。
🦆
题解中提到使用切片来实现数组的轮转,这种方式在面对极大的数组时效率如何?是否存在更高效的方法?
使用切片来实现数组的轮转简单直观,但在面对极大的数组时可能会有性能问题,因为切片操作涉及到额外的数组复制。在Python中,这种方法的时间复杂度是O(n),空间复杂度也是O(n)。存在更高效的方法,例如使用环状替换或三次数组翻转(先整体翻转,再翻转前k个元素,最后翻转剩余元素)实现原地旋转,可以将空间复杂度降低到O(1)。
🦆
题解中的方法是否能正确处理当`k`等于0或`k`等于数组长度的特殊情况?
是的,题解中的方法能正确处理这些特殊情况。当`k`等于0时,`k % len(nums)`的结果也是0,此时不会进行任何旋转,数组保持原样。当`k`等于数组长度时,`k % len(nums)`的结果同样是0,同样不进行任何旋转,数组也保持原样。因此,这种方法能够适应这些边界情况。

相关问题

旋转链表

给你一个链表的头节点 head ,旋转链表,将链表每个节点向右移动 k 个位置。

 

示例 1:

输入:head = [1,2,3,4,5], k = 2
输出:[4,5,1,2,3]

示例 2:

输入:head = [0,1,2], k = 4
输出:[2,0,1]

 

提示:

  • 链表中节点的数目在范围 [0, 500]
  • -100 <= Node.val <= 100
  • 0 <= k <= 2 * 109

反转字符串中的单词 II

反转字符串中的单词 II