赞
踩
给定一个数组,将数组中的元素向右移动 k
个位置,其中 k
是非负数。
思路:
关键点确定当前元素要去的位置。确定好要去的位置,将该位置上的元素备份(tag = 该位置的元素),然后替换成当前元素。此时被替换的位置变成了当前位置(否则被替换位置上的元素tag数据会丢失),且要进行移动的数为tag,继续进行要去的位置的查找然后替换。直到全部位置都被替换过。因为每个位置有且只有一次被替换,所以遍历总长度或者替换总次数应该=数组长度。
0 -> 3
3-> 6
6-> 9 9>7(长度不足,回返) 故6 -> 2
2 ->5
5 ->8 8>7(长度不足,回返) 故5 -> 1
1 ->4
4 ->7 7=7(长度不足,因为从0开始,回返) 故 4 -> 0
全部元素被替换完成。
要去的位置 = 当前位置+跨越长度,共有两种情况:
1:要去的位置 < 数组长度
根据余数的一个特点是 任何一个数除一个比本身大的数,余数为该数本身
所以:要去的位置 = (当前位置+跨越长度)% (数组长度)
2:要去的位置 > 数组长度
假设判断位置为 5 的元素要去的位置 5+3 = 8
1-7已经走过一圈的长度, 但还有一格未走,因为是环形,又回到了初始的位置1上。如图所示在环形上5要走3格,到达的位置也为 1
故:其余数为 回返之后的位置,该位置为要去的位置
特殊情况:当要去的位置 > 数组长度,并且数组长度为跨越长度的倍数时,会导致第一次回返的数值为 0 ,但此时0已经作为起始点移动过,需要手动将要移动的数的位置+1,否则将会一直不能遍历完数组,陷入死循环。
代码:
- void rotate(vector<int>& nums, int k)
- {
- if (nums.size() < 2 || k == 0)
- return;
- int changenumnow = nums[0], changenumnext = nums[0], tag = 0;
- int j = 0; // j 为移动后的位置
- int count = 0; // 记录移动次数
- if (k >= nums.size())
- {
- k = k % nums.size();
- }
- while (count != nums.size())
- {
- j = (j + k) % nums.size();
- changenumnext = nums[j];
- nums[j] = changenumnow;
-
- count++;
- // 回返的第一个数必为0,第二个为1,以此类推
- // 先判断回返的数 == 0,确定为特殊情况,并将起始位置+1,变成1,此时1也作为起始位置替换过其他元素,再次回返为1 时,操作同==0
- if (j == tag && j != nums.size()-1) //处理数组长度为步长倍数的情况
- {
- j = j + 1;
- tag = tag + 1; // 对0 1 2 3... 元素作为起始位置做标记,用来判断是否做过起始位置替换别的元素
- changenumnext = nums[j];
- }
- changenumnow = changenumnext;
- }
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。