C#旋转数组解决方案中特殊for循环的工作原理解析
旋转数组C#代码解析:for循环机制与逻辑拆解
这段代码是原地旋转数组的高效实现,核心通过分块交换完成旋转,不需要额外开辟数组空间。下面拆解重点部分:
外层for循环核心逻辑
for (; (p %= l) != 0; l -= p, index += p)
- 初始化部分为空:因为已经提前定义了
l(当前处理的数组块长度)和index(当前处理块的起始索引)。 - 循环条件
(p %= l) != 0:- 先执行
p %= l:把旋转步数p转换成当前数组块下的有效步数。比如数组长度是5,p=7的话,7%5=2,实际只需要旋转2步——毕竟旋转整倍数的数组长度等于没旋转,这一步避免做无用功。 - 当计算结果不为0时,继续循环;如果结果为0,说明
p是当前块长度的整数倍,旋转后和原块完全一致,直接终止循环。
- 先执行
- 循环后更新操作
l -= p, index += p:l -= p:当前块的前p个元素已经完成旋转交换,剩下需要处理的块长度缩短p。index += p:把处理的起始位置往后挪p位,接下来处理剩下的子数组块。
内层for循环:分块交换实现旋转
for (int i = 0; i < p; i++) { var temp = nums[l - p + i + index]; nums[l - p + i + index] = nums[i + index]; nums[i + index] = temp; }
这部分是做相邻块的元素一对一交换:
nums[i + index]:当前处理块的前p个元素中的第i个(已完成部分旋转的区域)。nums[l - p + i + index]:当前未处理区域的第i个元素(l-p是未处理区域相对于当前块的起始偏移,加上index得到全局索引)。- 交换这两个位置的元素,相当于把未处理区域的前
p个元素“挪”到已处理区域的对应位置,完成局部旋转。
实际例子验证(数组[1,2,3,4,5],p=2)
- 初始
l=5,index=0,p%5=2≠0,进入循环:- 内层循环交换
nums[0]和nums[3]、nums[1]和nums[4],数组变为[4,5,3,1,2]。
- 内层循环交换
- 更新
l=5-2=3,index=0+2=2:- 计算
p%3=2≠0,再次进入循环: - 内层循环交换
nums[2]和nums[3]、nums[3]和nums[4],数组变为[4,5,1,2,3]。
- 计算
- 更新
l=3-2=1,index=2+2=4:- 计算
p%1=0,循环终止,最终得到旋转2步的正确结果。
- 计算
内容的提问来源于stack exchange,提问作者pin
相关产品推荐
相关产品推荐

