目录
1,题目描述
英文描述
中文描述
2,解题思路
方法一:环状替换
方法二:反转
3,AC代码
方法一:环状替换
C++
Java
方法二:反转
C++
4,解题过程
第一博
第二搏
第三搏
原题链接189. 旋转数组;
虽说是简单题,但是算法还是很巧妙的!
Given an array, rotate the array to the right by k steps, where k is non-negative.
Follow up:
Try to come up as many solutions as you can, there are at least 3 different ways to solve this problem. Could you do it in-place with O(1) extra space?
Example 1:
Input: nums = [1,2,3,4,5,6,7], k = 3 Output: [5,6,7,1,2,3,4] Explanation: rotate 1 steps to the right: [7,1,2,3,4,5,6] rotate 2 steps to the right: [6,7,1,2,3,4,5] rotate 3 steps to the right: [5,6,7,1,2,3,4]
Example 2:
Input: nums = [-1,-100,3,99], k = 2 Output: [3,99,-1,-100] Explanation: rotate 1 steps to the right: [99,-1,-100,3] rotate 2 steps to the right: [3,99,-1,-100]
Constraints:
1 <= nums.length <= 2 * 10^4 It's guaranteed that nums[i] fits in a 32 bit-signed integer. k >= 0
给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。
示例 1:
输入: [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] 示例 2:
输入: [-1,-100,3,99] 和 k = 2 输出: [3,99,-1,-100] 解释: 向右旋转 1 步: [99,-1,-100,3] 向右旋转 2 步: [3,99,-1,-100] 说明:
尽可能想出更多的解决方案,至少有三种不同的方法可以解决这个问题。 要求使用空间复杂度为 O(1) 的 原地 算法。
来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/rotate-array 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
参考@力扣 (LeetCode)【旋转数组】
通过观察交换位置的坐标关系,可以发现:
每将一个元素放入到最终位置时,可以得到下一个元素以及该元素的最终位置,以此类推,通过类似于一个环状替换的过程,可以将该环中涉及到的元素放置在最终位置上;
通过交换的次数来判断算法是否完成(交换次数count==数组长度时,算法完成);
若一个环遍历完毕,且算法未结束,说明还存在其他的环,所以调整下一个环开始的位置(从0开始递增即可),继续进行环状替换;
原始数组 : 1 2 3 4 5 6 7
反转所有数字后 : 7 6 5 4 3 2 1
反转前 k 个数字后 : 5 6 7 4 3 2 1
反转后 n-k 个数字后 : 5 6 7 1 2 3 4 --> 结果
一开始,针对给出的样例,手动写了交换元素间的坐标位置关系:0-3,0-6,0-2,0-5,0-1,0-4,这样7个元素,交换六次就可以实现。然而前提是只有一个环,有的用例含有多个环,上述解法就需要动态修改一些边界,很容易出错。
参考官网给出的解法,其中解法三和我的思路很像,只不过采用变量prev保存将要交换的元素,并且利用count计数,这样可以保证每个位置都交换一次。
一旦当前位置和起始位置重合,开始循环下一个环
通过记录 交换的次数 来判断算法是否终止,这样可以实现多个环的交换。
时间O(N),空间O(1),只遍历一次数组;
另一种方法是,将整个数组前后对调,再将前k个元素和剩余的元素分别对调,这样即可得到最终答案,相当于完整遍历了两次数组;
时间O(N),空间O(1);