题目
189 旋转数组
给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。
输入: [1,2,3,4,5,6,7] 和 k = 3
输出: [5,6,7,1,2,3,4]
解释: 向右旋转 1 步: [7,1,2,3,4,5,6]
向右旋转 2 步: [6,7,1,2,3,4,5]
向右旋转 3 步: [5,6,7,1,2,3,4]
链接:https://leetcode-cn.com/problems/rotate-array
解法一
按示例所说,即该旋转几次就按顺序旋转几次。
时间复杂度:O(kn)
空间复杂度:O(1)
public void Rotate1(int[] nums, int k)
{
k %= nums.Length;
if(nums.Length < 2)
return;
var temp = nums[nums.Length - 1];
for(int i = 0;i<k;i++)
{
temp = nums[nums.Length - 1];
for(int n = nums.Length-1;n>0;n--)
{
nums[n] = nums[n-1];
}
nums[0] = temp;
}
}
解法二
放眼宏观,巧妙的利用数组的翻转,例如
[1,2,3,4,5,6,7] k = 3
拆分成三步:
1.整体翻转数组 [7,6,5,4,3,2,1]
2.以K索引为界限 翻转前半段 [5,6,7,4,3,2,1]
3.再翻转后半段 [5,6,7,1,2,3,4]
时间复杂度:O(n)
空间复杂度:O(1)
public void Rotate2(int[] nums, int k)
{
k %= nums.Length;
if(nums.Length < 2 || k<= 0)
return;
Array.Reverse(nums,0,nums.Length);
Array.Reverse(nums,0,k);
Array.Reverse(nums,k,nums.Length - k);
}
解法三
跟踪细节,将每一次替换形成一个闭环。
官方提供的这个图就非常的好理解这种解法。
每次交换操作我们不是只针对数组中的两个数来进行,而是完成一个闭环的交换过程。
比如:1 => 3 ,3 => 5 ,5 => 1
时间复杂度:O(n)
空间复杂度:O(1)
public void Rotate3(int[] nums, int k)
{
k %= nums.Length;
if(nums.Length < 2 || k<= 0)
return;
var swopCount = 0;
for(int i = 0;swopCount<nums.Length;i++)
{
var cur = i;
var temp = nums[i];
do
{
var next = (cur + k) % nums.Length;
var t = nums[next];
nums[next] = temp;
temp = t;
cur = next;
swopCount++;
}
while (cur != i);
}
}