189. 轮转数组
给定一个整数数组 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
暴力法
这个题目最容易想到的解法就是直接暴力求解,将数组旋转k次,时间复杂度是O(N^2),空间复杂度是O(1)。
void rotate(int* nums, int numsSize, int k) { k = k%numsSize; int value; for(int i = 0;i<k;i++) { value = nums[numsSize-1]; for(int j = numsSize-1;j>0;j--) { nums[j]=nums[j-1]; } nums[0]=value; } }
辅助空间法
第二个比较容易想到的思路是用空间换时间,也即另外开辟一个数组,将从第k个位置开始的数组元素依次放在另一个数组中,最后返回这个数组,这个方法的时间复杂度是O(N),空间复杂度也是O(N)。
void rotate(int* nums, int numsSize, int k) { int newArr[numsSize]; for (int i = 0; i < numsSize; ++i) { newArr[(i + k) % numsSize] = nums[i]; } for (int i = 0; i < numsSize; ++i) { nums[i] = newArr[i]; } }
三段逆置法
这篇博客主要讲解是下面这个方法,三段逆置法。
三次逆置数组对应元素即可完成将数组中的元素向右轮转 k 个位置的要求。
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> void reverse(int*a, int left, int right) { while (left < right) { int tmp = a[left]; a[left] = a[right]; a[right] = tmp; left++; right--; } } void rotate(int* a, int k, int NumsSize) { reverse(a, 0, NumsSize - k - 1); reverse(a, NumsSize - k, NumsSize - 1); reverse(a, 0, NumsSize - 1); } int main() { int a[] = {1,2,3,4,5,6,7}; rotate(a,3, sizeof(a) / sizeof(a[0])); for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++) { printf("%d ", a[i]); } return 0; }
这个方法是模仿大佬的写法,我目前是肯定想不出来的,唉。。。不知道大佬们的脑子是怎么长得。。。。。。