
1.本题和力扣第151题-反转字符串中的单词很像,可以将数组轮转之后的最终形态看成左右两个单词,这个单词是通过原数组整体反转后再在单词处局部反转得来的。完整代码如下:
cpp
1. // 交换两个整数的值
2. void swap(int* a, int* b){
3. int tmp = *a;
4. *a = *b;
5. *b = tmp;
6. }
7.
8. void rotate(int* nums, int numsSize, int k) {
9. // k超过数组长度时取模,消除多余旋转次数
10. k %= numsSize;
11. // 第一次反转:整个数组全部反转
12. for (int i = 0; i < numsSize / 2; i++){
13. swap(&nums[i], &nums[numsSize - i - 1]);
14. }
15.
16. // 第二次反转:前k个元素反转
17. for (int i = 0; i < k / 2; i++){
18. swap(&nums[i], &nums[k - i - 1]);
19. }
20. // 第三次反转:剩余numsSize-k个元素反转
21. for (int i = k; i < (numsSize + k) / 2; i++){
22. swap(&nums[i], &nums[numsSize - i + k - 1]);
23. }
24. }
该算法时间复杂度为O(n),空间复杂度为O(1)。
2.本题官方还给出了一种环状替换的方法,十分复杂,自己做的时候也想不到,这里只把代码和解析放出来:

cpp
1. // 欧几里得算法求最大公约数
2. int gcd(int a, int b) {
3. return b ? gcd(b, a % b) : a;
4. }
5.
6. // 交换两个整型变量的值
7. void swap(int* a, int* b) {
8. int t = *a;
9. *a = *b, *b = t;
10. }
11.
12. void rotate(int* nums, int numsSize, int k) {
13. // 消除多余旋转次数
14. k = k % numsSize;
15. // 需要处理的环的数量为 k 和数组长度的最大公约数
16. int count = gcd(k, numsSize);
17. // 遍历每一个环
18. for (int start = 0; start < count; ++start) {
19. int current = start;
20. int prev = nums[start];
21. do {
22. // 计算当前位置向右移动k步后的下标
23. int next = (current + k) % numsSize;
24. // 将待放置的值交换到next位置
25. swap(&nums[next], &prev);
26. current = next;
27. } while (start != current); // 回到起点,当前环处理完成
28. }
29. }
该算法时间复杂度为O(n),空间复杂度为O(1)。