进行n/2次(n*n的矩阵有n/2圈的空心圈)的循环围绕矩阵外围遍历到内里。每条边的遍历不处理当前边的最后一个节点,留给下一条边作为起始处理,能够保证每条边处理的元素个数相同。因为循环遍历是从外到内的圈,因此当n为奇数时留下最中心的元素形成不了圈,要单独判断赋值。
- 一圈的四条边分别循环,设置start变量记录每一圈的起始点为对角线坐标
- (0,0)->(0,1)->(0,2)->(1,2)坐标变化为 ++ ;
- (2,2)->(2,1)->(2,0)->(1,0)坐标变化为 -- ;
- 不断循环完矩阵外圈才判断处理最中心的元素 -> 使用循环遍历后用if语句判断n是否为奇数(存在中心点,为中心点赋值,中心点又能理解为下一圈的起点,因此使用(start,start)进行赋值)
输入:n = 3
输出:[ [1,2,3], [8,9,4], [7,6,5] ] 在二维矩阵中的对应位置如下:
圈数:1 -> 需进行1次的外圈循环 控制圈数的变量times = 1
中心点:有 -> 最后需进行中心点赋值
起始点为 (0,0),start = 0
为元素赋值 num = 1
(0,0) | (0,1) | (0,2) |
(1,0) | (1,1) | (1,2) |
(2,0) | (2,1) | (2,2) |
每次开始时都是在对角上的元素,因此每一圈的第一行遍历的开始位置为(start,start)不为 (i,j)(当遍历一圈的最后一行操作时 i 还在外圈,不在下一圈的开始位置;如遍历到最后一列时为遍历(2,0)->(1,0),遍历结束后 i = 1)
遍历(0,0),(0,1)
j < n - times = 2(j = 0,1)
每次遍历时 i 不变,j++(即行不变,列变),num++(计数+1);
每遍历完一圈,里面的一圈都比外面一圈少一个元素,因此要控制 i,j 遍历次数,使用n - times;(times 每遍历完一圈后+1)
1 | 2 | (0,2) |
(1,0) | (1,1) | (1,2) |
(2,0) | (2,1) | (2,2) |
上一次遍历结束后:i = start,j = 2,num = 3;
遍历(0,2),(1,2)
i < n - times = 2(i = 0,1)
每次遍历时 j 不变,i++(即行变,列不变),num++(计数+1);
1 | 2 | 3 |
(1,0) | (1,1) | 4 |
(2,0) | (2,1) | (2,2) |
上一次遍历结束后:i = 2,j = 2,num = 5;
遍历(2,2),(2,1)
j > start = 0,j--(j = 2,1) 因为 j 要从2 -> 1,需变换循环条件为 j > start
每次遍历时 i 不变,j--(即行不变,列变),num++(计数+1);
1 | 2 | 3 |
(1,0) | (1,1) | 4 |
(2,0) | 6 | 5 |
上一次遍历结束后:i = 2,j = 0,num = 7;
遍历(2,0),(1,0)
i > start = 0,i--(i = 2,1) 因为 i 要从2 -> 1,需变换循环条件为 i > start
每次遍历时 j 不变,i--(即行变,列不变),num++(计数+1);
一圈循环结束后,start++,进入下一圈循环;
1 | 2 | 3 |
8 | (1,1) | 4 |
7 | 6 | 5 |
上一次遍历结束后:i = 1,j = 0,num = 9,start = 1;
由此看出起始位置不能单纯使用 i,j ,而应该使用start作为行和列的起始。
剩单个元素,直接将num值放入下一圈的起始位置,不需要进入循环,即(start,start)= 9
1 | 2 | 3 |
8 | 9 | 4 |
7 | 6 | 5 |