空间复杂度O(1) 解决旋转数组的三种方式(LeetCode)

题目

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);
	}
}
原创文章 28 获赞 30 访问量 2434

猜你喜欢

转载自blog.csdn.net/qq_28820675/article/details/105349789