刷题使我快乐,满脸开心.jpg
- 来源:力扣(LeetCode)
- 链接:https://leetcode.cn/problems/rotate-array/
- 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题目
给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。
示例 1:
输入: nums = [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:
输入:nums = [-1,-100,3,99], k = 2
输出:[3,99,-1,-100]
解释: 
向右轮转 1 步: [99,-1,-100,3]
向右轮转 2 步: [3,99,-1,-100]
提示:
- 1 <= nums.length <= 10^5
- -2^31 <= nums[i] <= 2^31 - 1
- 0 <= k <= 10^5
进阶:
- 尽可能想出更多的解决方案,至少有 三种不同的方法可以解决这个问题。
- 你可以使用空间复杂度为 O(1)的原地算法解决这个问题吗?
思路
额外数组
这个思路很简单,空间复杂度高一些记录下就好了
循环交替
这个思路就是不断往后交换,直接把数字摆到它应该在的位置,会有几个注意点:
- 用额外变量存下来下一个数字,便于持续往后计算
- 记录初始点,用是否回到初始点决定是否需要往右移动一位继续往后交换
- 记录总共摆放的次数,因为没有限制,会一直往后交换下去,其实我们简单画一下就明白,有可能交换回初始点时,很多位置就已经完成了,初始点右移是有可能把已经摆好位置的数字移动到错误位置,所以要限制总计交换次数
翻转数组
一图胜千言

大体思路就是这样了,上代码~
代码
交替
func rotate(nums []int, k int) {
	// 整除就直接return
	if k%len(nums) == 0 {
		return
	}
	p := 0
	// 把k取余,最多需要这么多起始点就够了
	k = k % len(nums)
    // 记录起始点
	startP := 0
    // 计算要摆放位置
	nextP := 0
    // 缓存下个要摆放的数字
	back := 0
    // 总计移动次数
	count := 0
    // 摆够了就不用继续了
	for startP < k && count < len(nums) {
		p = startP
		back = nums[p]
		for count < len(nums) {
            // 计算下个摆放位置
			nextP = (p + k) % len(nums)
            // 存下个摆放数字
			back, nums[nextP] = nums[nextP], back
            // 步进
			p = nextP
            // 统计摆放次数
			count++
            // 回到起始点就换个起始点
			if p == startP {
				break
			}
		}
        // 步进起始点
		startP++
	}
}
翻转
func reverse(a []int) {
	for i, j := 0, len(a)-1; i < j; i, j = i+1, j-1 {
		a[i], a[j] = a[j], a[i]
	}
}
func rotate(nums []int, k int) {
    // 计算旋转点
	n := k % len(nums)
    // 全量翻转
	reverse(nums)
    // 分别部分翻转
	reverse(nums[:n])
	reverse(nums[n:])
}
