【leetcode之189. 轮转数组】详解
原题
链接:https://leetcode.cn/problems/rotate-array/:
很有意思的一道题,本人提供三种方法,有更巧妙的方法的同学欢迎交流
正文开始
一、Create a new array
创建一个新数组,拿新数组进行(i+k)%numsize=i进行元素的偏移以达到题目目的,
再把新数组赋值给原先数组
图解:
代码实现:
void rotate(int* nums, int numsSize, int k){
int num1[numsSize];
for(int i=0;i<numsSize;i++)
{
num1[(i+k)%numsSize]=nums[i];
}
for(int i=0;i<numsSize;i++){
nums[i]=num1[i];
}
}
该方法时间复杂度为O(N),该方法创建了一个新数组,消耗内存,下面两种方法可以进一步优化
二、Array flipping
这个方法极奇难以想到,但是你见过一次就难以忘怀。
思路:
- 将整个数组翻转
- 将翻转后的数组从第0个到第k-1个翻转
- 将翻转后的数组从第k个到第numsize个翻转
图解如下
代码实现:
void swap(int* a, int* b) {
int t = *a;
*a = *b, *b = t;
}
void reverse(int* nums, int start, int end) {
while (start < end) {
swap(&nums[start], &nums[end]);
start += 1;
end -= 1;
}
}
void rotate(int* nums, int numsSize, int k) {
k %= numsSize;
reverse(nums, 0, numsSize - 1);
reverse(nums, 0, k - 1);
reverse(nums, k, numsSize - 1);
}
三.Ring substitution
解题技巧:
- 我们可以把数组看成一个圆环,只要访问数组下标超过numsize就对numsize取余
- 因为把一个元素i向后挪k个位置,那么第(i+k-1)个位置的元素势必被覆盖,故我们想到使用一个中间变量接收,然后再进行中间变量和第(i+k-1)进行交换,使中间变量不断后移。
- 直到中间变量等与从开始的元素相等,第一次轮转结束
图解:
得到结果
代码实现:
void swap(int* a, int* b)
{
int t;
t = *a;
*a = *b;
*b = t;
}
void rotate(int* nums, int numsSize, int k)
{
int cnt = 0;
int temp, p;
for (int start = 0; start < numsSize; start++)
{
temp = nums[start];
p = start;
do
{
p = (p + k) % numsSize;
swap(&temp, &nums[p]);
cnt++;
} while (p != start);
if (cnt == numsSize) break;
}
}
执行结果:
该方法时间复杂度为O(1),内存消耗较小,效率较高
总结
第一种方法各位务必要掌握
第二种和第三种了解仅可
一天不力扣我就浑身难受。
--莎士比亚