轮转数组(C语言)
作者:互联网
文章目录
【题目描述】
给你一个数组,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。
题目来源(力扣):轮转数组
示例1:
输入: nums = [1,2,3,4,5,6,7], k = 3
输出: [5,6,7,1,2,3,4]
示例2:
输入:nums = [-1,-100,3,99], k = 2
输出:[3,99,-1,-100]
注:0 <= k <= 10^5
在讲这道题之前,我们首先要知道这么一个点:
如果一个数组有 n 个元素,那么当它向右轮转了 n 步之后,整个数组跟原来一样。
也就是 k = n 的效果跟 k = 0 的效果是一样的,
即对 k 做这样的处理: k %= numsSize 即可。(对 k >= n 都成立)
思路正确但不实际的解法
基本思路:
先复制最后一个元素,然后将前面的元素都向右轮转一步,最后将原来的最后的元素放到首元素位置。把这个操作循环 k 次,就能得到结果。
void rotate(int* nums, int numsSize, int k){
k %= numsSize;
for(int i = 0; i < k; i++)
{
int tmp = nums[numsSize - 1];
for(int j = numsSize - 1; j > 0; j--)
{
nums[j] = nums[j - 1];
}
nums[0] = tmp;
}
}
但是这种方法的时间复杂度是 O(n^2),效率太低,特别是在数据量很大的情况下。
可行但不实际,所以大胆舍弃它。
解法一
基本思路:
开辟额外的数组,把每个元素放到新开辟的数组的轮转 k 步后的位置,最后再复制回原数组。
总的来说就是以空间换时间,通过牺牲一定的空间来优化时间效率。
void rotate(int* nums, int numsSize, int k){
int* tmp = (int*)malloc(sizeof(int)*numsSize);
for (int i = 0; i < numsSize; i++)
{
tmp[(i + k) % numsSize] = nums[i]; //把每个元素放到新开辟的数组的轮转 k 步后的位置
}
for(int i = 0; i < numsSize; i++)
{
nums[i] = tmp[i];
}
free(tmp);
tmp = NULL;
}
时间复杂度是 O(n),空间复杂度也是O(n),还是可行的,但存在额外的空间开销。
解法二
这种方法很巧,没接触过类似题型的大概想不到。
基本思路:
先把整体逆序,然后根据 k 把数组划分为两部分,分别逆序这两部分。
void reverse(int * nums, int left,int right)
{
while (left < right)
{
int tmp = nums[left];
nums[left] = nums[right];
nums[right] = tmp;
left++;
right--;
}
}
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);
}
时间复杂度是 O(n),空间复杂度是O(1),不需要额外的空间开销即可解决问题,算得上是最优解了。
更多文章
采用快慢指针法来解决有关数组的问题(C语言)
异或的妙用(C语言)
大数相加(C语言)
合并两个有序数组(C语言)
阶乘后的零(C语言)
调整数组顺序使奇数位于偶数前面(C语言)
标签:numsSize,tmp,轮转,nums,int,C语言,数组 来源: https://blog.csdn.net/m0_59938453/article/details/122013159