[LeetCode 189] 轮转数组

时间:2025-04-12 06:58:50

[LeetCode 189] 轮转数组

题目描述:

给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。
示例 1:
输入: nums = [1,2,3,4,5,6,7], k = 3
输出: [5,6,7,1,2,3,4]
示例 2:
输入:nums = [-1,-100,3,99], k = 2
输出:[3,99,-1,-100]
范围:
1 ≤ n u m s . l e n g t h ≤ 105 1 \le nums.length \le 105 1nums.length105
− 2 31 ≤ n u m s [ i ] ≤ 2 31 − 1 -2^{31} \le nums[i] \le 2^{31} - 1 231nums[i]2311
0 ≤ k ≤ 1 0 5 0 \le k \le 10^5 0k105

思路:

1. 暴力new数组存储

void rotate(vector<int>& nums, int k) {
     size_tn = nums.size();
     vector<int> temp(n, 0);
     for(size_t i = 0; i < nums.size(); ++ i)
         temp[(i + k) % n] = nums[i];
     nums = temp;
     return ;
 }

2. 数组翻转 & 双指针

这边双指针指的是如果要自己写 r e v e r s e reverse reverse 的话。

(思路copy官方题解,but 王道考研里遇到过,很简单的逻辑)
该方法基于如下的事实:当我们将数组的元素向右移动 k k k 次后,尾部 k   m o d   n k\ mod\ n k mod n 个元素会移动至数组头部,其余元素向后移动 k   m o d   n k\ mod\ n k mod n 个位置。
该方法为数组的翻转:我们可以先将所有元素翻转,这样尾部的 k   m o d   n k\ mod\ n k mod n 个元素就被移至数组头部,然后我们再翻转 [ 0 , k   m o d   n − 1 ] [0,k\ mod\ n−1] [0,k mod n1] 区间的元素和 [ k   m o d   n , n − 1 ] [k\ mod\ n,n−1] [k mod n,n1] 区间的元素即能得到最后的答案。

	void Reverse(vector<int>& nums, int start, int end) {
	    while(start < end) {
	        swap(nums[start], nums[end]);
	        start++;
	        end--;
	    }
	}
	void rotate(vector<int>& nums, int k) {
	    k %= nums.size();
	    Reverse(nums, 0, nums.size() - 1);
	    Reverse(nums, 0, k - 1);
	    Reverse(nums, k, nums.size() - 1);
	    /**
	    or use stl reverse
	    reverse(nums.begin(), nums.end());
	    reverse(nums.begin(), nums.begin() + k);
	    reverse(nums.begin() + k, nums,end());
	    **/
	}

3. 原地轮转替换

最优但不好理解,umm maybe尝试群论/数论可以理解
(退步太多,思维缓慢,重新刷题,勉励自己)
两篇文章可帮助理解:blog 1blog 2

void rotate(vector<int>& nums, int k) {
     k %= nums.size();
     int n = nums.size();
     int cnt = gcd(n, k);
     for(int i = 0; i < cnt; ++ i) {
         int j = i;
         int pre = nums[i];
         do{
             int ne = (j + k) % n;
             swap(nums[ne], pre);
             j = ne;
         } while(i != j);
     }
 }