题目链接:. - 力扣(LeetCode). - 备战技术面试?力扣提供海量技术面试资源,帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/rotate-array/?envType=list&envId=QJxfEzqo
题目:给定一个整数数组 nums
,将数组中的元素向右轮转 k
个位置,其中 k
是非负数。
示例:
void rotate(int* nums, int numsSize, int k) {}
nums数组的地址,numsSize是数组的大小(方便起见,后面用n代指),k直的是向右轮转的次数。
方法一:使用额外数组
思路:我们先创建一个新的数组,将原数组中的数根据k计算出在轮转之后的位置,然后放置在新数组中,遍历整个数组,直到完成所有元素的放置,最终将新数组的内容依次还给原数组。
假设这里有一个大小为5的数组,如果我们要轮转3次,那么第4个位置上的数就会到第二个位置上去。也就是第i个位置上的数会到第(i+k)%numsSize位置上去。直到了这个也就掌握了这个方法的关键所在。
然后我们知道轮转numsSize次,等于没有轮转,所以当k的值大于numsSize时,我们可以取余一次。
代码:
void rotate(int* nums, int numsSize, int k) {int newArr[numsSize];//创建一个同类型的数组//创建一个新的数组int k = k % numsSize;for (int i = 0; i < numsSize; i++) {newArr[(i + k) % numsSize] = nums[i];//根据k来得到旋转后的位置;}for (int j = 0; j < numsSize; j++) {nums[j] = newArr[j];//将新数组的数还给原数组。}
}
方法二:三次逆置法/翻转数组法
假设这里有五个数,将其向右轮转2。
我们会发现第三次 就是我们所要的结果,那么是如何翻转的呢?
第一次是将后k个数逆置,第二次是将前n-k个数进行逆置,第三次是将整体进行逆置。这样就实现了k次轮转。
代码:
void reverse(int *a,int left,int right){while(left<right){int tmp = a[right];a[right] = a[left];a[left] = tmp;left++;right--;}
}
void rotate(int* nums, int numsSize, int k) {k %= numsSize;reverse(nums,numsSize - k,numsSize - 1);//逆置后面k个数reverse(nums,0,numsSize - k - 1);//逆置前面n-k个数reverse(nums,0,numsSize - 1);。。整体逆置}
这种方法第一次做难以想到,这与数学有关。
方法三:memcpy函数
我们可以使用memcpy函数解决这道题。
我们首先分配一个临时内存,我们将原数组的后k个数,拷贝到这个临时空间中,再将前n-k数拷贝到tmp+k的地方,这样我们就实现了数组的轮转,只不过不是原数组,最后我们再将tmp拷贝到原数组中就完成了。
void rotate(int* nums, int numsSize, int k) {k = k % numsSize;int *tmp = (int*)malloc(sizeof(int)*numsSize);memcpy(tmp+k,nums,sizeof(int)*(numsSize-k));memcpy(tmp,nums+numsSize-k,sizeof(int)*k);memcpy(nums,tmp,sizeof(int)*numsSize);free(tmp);tmp = NULL;
}