题目:
给定一个数组,将数组中的元素向右移动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;
}