1、题目
给定一个整数数组 nums
,将数组中的元素向右轮转 k
个位置,其中 k
是非负数。
下面是一个示例:
输入: 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、思路
图解如下:
观察发现,轮转后的数组与原数组相比有一部分元素移动至数组头部,有一部分元素移动至数组尾部。因此考虑先反转数组,然后反转数组前段,最后反转数组后段。
注意: k可能大于等于数组长度,应该确保k<=数组长度,避免出现访问越界。
分三步反转:
-
反转整个数组
-
反转前k个元素
-
反转后n-k个元素
代码实现
//反转函数
void reverse(int* nums, int left, int right)
{
while(left < right)
{
//反转左右指针指向的元素
int tmp = nums[left];
nums[left++] = nums[right];
nums[right--] = tmp;
}
}
void rotate(int* nums, int numsSize, int k)
{
//k大于元素个数,应当减小n倍元素个数,因为反转元素个数个位置,顺序和原数组一样,相当于没反转
//k大于数组长度的极端情况
k %= numsSize;
//三段反转
//反转数组整体
reverse(nums, 0, numsSize-1);
//反转轮转部分
reverse(nums, 0, k-1);
//反转非轮转部分
reverse(nums, k, numsSize-1);
}
3、复杂度
时间复杂度:N是数组长度
- 反转数组整体,遍历一次数组为O(N)
- 反转轮转部分,遍历k个元素为O(1)
- 反转非轮转部分,遍历n-k个元素为O(N)
所以整个时间复杂度为O(N)。
空间复杂度:在原数组的空间上,仅交换数组内元素,没有申请额外的空间,空间复杂度为O(1)。