)
前言:
新开一个专栏
要学好编程肯定得多敲代码,于是刷题提高是重要的过程
该栏目内容专门记录刷leetcode题目以及刷题笔记,记录做题方法,巩固提高。
在做题之前我们需要了解一个东西
一般,常见的在线OJ的两种类型:接口型和IO型。接口型:测试用例和结果一般是通过参数接口函数的参数和返回值交互和判对错,一般不需要写函数,直接调用参数即可。
IO型:测试用例通过IO输入输出,需要自己写头文件、main函数,自己写输入获取测试用例。
这两种OJ类型本质类同,都是通过网络传到后台服务器,去运行所写的程序,通过测试用例检测正确性。
那么这是一道来自leetcode的题目,题目描述如下:
以下给出题目的链接,方便大家去练习。
同样的网站上也给出了提示
同时这是一道接口型在线OJ,题目给出了接口函数和参数,如下:
void rotate(int* nums, int numsSize, int k){
}
接下来开始手撕题目,这题本身并不难
但是这种题目三种想法可以有效地开阔思路,特别是第三种方法,多刷刷这种题目将对本类题型有新的看法。
那么针对这道题目的话,我们有三种思路。
想法一:最朴素思路
整体概括为实现一个可以反转一次一个数字的循环,然后实现k次该循环,就实现了k次翻转。这里不开辟新数组
时间复杂度 | o(K*N) |
---|---|
空间复杂度 | o(1) |
void rotate(int* nums, int numsSize, int k) {
int tmp = 0;
while (k >= numsSize)
{
k %= numsSize;
}
for (int i = 0; i < k; i++)
{
tmp = nums[numsSize - 1];
for (int j = 0; j < numsSize - 1; j++)
{
nums[numsSize - 1-j] = nums[numsSize - 2-j];
}
nums[0] = tmp;
}
}
我们主要的想法是创建一个tmp,利用tmp存放最后一个数,然后将前面numsSize-1个数往后移,这样可以实现1次旋转,如果我们要操作k次就是重复k次这样的操作就可以了。
但是这里为了减少冗余操作,我们写了一个循环如果K是>整个数组长度的话,那么我们利用%取模方法来将其降低为最少等同结果得次数并输出,这样就可以减少无必要的操作,这个循环后面依然会用到。
然而一次旋转得时间复杂度就是O(N),如果转k次就是o(K*N)
所以经过测试,遇到大量数据就无法通过leetcode
想法二:利用新数组
这里我们的想法是为了不改变原先的数组排列顺序,我们要创建一个新的数组,其本质就是把第numsSize-k个数字变成新数组的第一个数组元素,然后依次放入按顺序新数组中。
时间复杂度 | o(N) |
---|---|
空间复杂度 | o(N) |
实现如下:
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];
}
当然也可以把numsSize-k之后的数放在最前,然后再后面接numsSize-k之前的数,都可以
想法三:3次逆置法
这个方法地主要思路是有技巧性和有规律的,也是效果最好的,我们需要对原数组实现三次逆置
时间复杂度 | o(N) |
---|---|
空间复杂度 | o(1) |
三次倒置分别是
1.对原数组的前n-k个数倒置
2.对原数组的后k个数倒置
3.对原数组整体逆置
就可以完成旋转了
这里我们最好是写一个reverse函数,是数组倒置,数组导致函数 本身是很好写的,然后改变参数调用三次就可以了。
代码实现如下:
void reverse(int* num, int left, int right)
{
while (left < right)
{
int tmp = num[left];
num[left] = num[right];
num[right] = tmp;
++left;
--right;
}
}
void rotate3(int* nums, int numsSize, int k)
{
while (k >= numsSize)
{
k %= numsSize;
}
reverse(nums, 0, numsSize - k - 1);//前k个数
reverse(nums, numsSize-k, numsSize-1);//后k个数
reverse(nums, 0, numsSize- 1);//整个数组
}
但是这里我们需要注意一个点
倘若numsSize这里要比k来的小,我们就会导致这个传到reverse函数的left或right<0,这样明显无发正确运行我们的程序,所以接下来的问题是要使得k比numsSize小,还是一样用%来使得k<numsSize就可以解决。
总结:
以上就是本道题的三种想法
如果你觉得写的还行,有点收获,那么请给我三连(点赞、收藏、关注)吧,谢谢。