题目:
给定一个数组,将数组中的元素向右移动k个位置,其中k是正整数。
进阶:
- 尽可能相处更多的解决方案,至少有三种不同的方法可以解决这个问题。
- 你可以使用空间复杂度为O(1)算法解决这个问题吗?
示例
解答:
思路1:一步一步进行分解
向右旋转一步时,可以将最右边的数移到第一个位置上,然后num-1向右移动一位,再嵌套循环k次。
源码:
int main() { int num[7] = { 1,2,3,4,5,6,7 }; int k = 0; cin >> k; while (k--) { int tmp = num[6]; for (int i = 6; i >0; i--) { num[i] = num[i - 1];//直接写-1,不需要写i-- }//倒着写! num[0] = tmp; } for (int i=0;i<7;i++) { cout << num[i] << ' '; } return 0; }
反思:
这种解法的时间复杂度是O(n*k),低效率,当数据一多,容易跑崩掉。空间复杂度是O(1)
思路2:用空间换时间
直接开辟一个新数组,将经过k次旋转的前后两个部分直接拷贝到一个新的数组里面。
反思:
时间效率提高了,但是所需要的空间变大了,首先不符合题意满足空间复杂度是O(1),其次若题目给的数据过多,空间也可能不够!
思路三:最牛的解法
这种算法的时间复杂度是O(n),空间复杂度为O(1)
该解法最核心部分是如何实现逆置。
用左右下标表示前后逆置的对象,然后left++,right--,直到不满足left<right即可。
void fun(int *arr,int left,int right)//是左右数组下标 { while (left < right) { int tmp = arr[left]; arr[left] = arr[right]; arr[right] = tmp; left++; right--; } } int main() { int arr[7] = { 1,2,3,4,5,6,7 }; int k; cin >> k; int num = 7; if (k > 7) { num %= 7; }//需要判断旋转次数大于数组的长度时,数组会越界! fun(arr,7-k,6);//后k个逆置 fun(arr,0,7-k-1);//前n-k个逆置 fun(arr,0,6);//整体逆置 for (int i=0;i<7;i++) { cout << arr[i] << ' '; } return 0; }