解 旋转数组

时间:2021-03-10 00:40:47

题目:

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