解法一:暴力法
以倒数第k个位置为分界点,将前后两半子数组调换一下,组成新数组即为答案
func rotate(nums []int, k int) {
if k > len(nums) {
k = k%len(nums)
}
lastK := nums[len(nums)-k:] // 倒数k个元素
front := nums[:len(nums)-k] // 前半部分
res := append(lastK, front...) // 置换两部分子数组
for i:=0; i<len(nums); i++{ // 答案更新到原数组上
nums[i] = res[i]
}
}
好家伙,一个暴力法耗时击败100%?
但显然,空间复杂度有待优化,这里可以考虑原地置换数组,省去上面申请的3个临时数组lastK, front, res
解法二:反转数组
向右轮转k个元素,其实就是把分别包含前 len(nums)-k个元素和后 k个元素的两个子数组交换位置,子数组内部元素要保持原来的顺序不变,
这样的话,先逆置整个数组,这样两个子数组就互换位置了,但是这样两个子数组内部的元素顺序也逆置了,那么就分别逆置一次两个子数组里的元素,这样子数组就恢复原来的顺序,轮换就完成了。
func rotate(nums []int, k int) {
if k > len(nums) {
k = k%len(nums)
}
slices.Reverse(nums) // 反转整个数组
slices.Reverse(nums[:k]) // 反转前k个元素
slices.Reverse(nums[k:]) // 反转后len-k个元素
}
不调内部包能否手撕?安排!
解法三:原地反转数组,双指针法
func rotate(nums []int, k int) {
if k > len(nums) {
k = k%len(nums)
}
reverseList(nums)
reverseList(nums[:k])
reverseList(nums[k:])
}
func reverseList(nums []int) {
left, right := 0, len(nums)-1
for left < right{
nums[left], nums[right] = nums[right], nums[left]
left++
right--
}
}