题目:
给定一个矩阵,按Z字形的顺序输出整个矩阵。所谓Z字形即如下所示:
按如上的Z字形顺序打印这个矩阵,将会得到:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16这个序列。
解法一:
对于这个顺序,我们可以利用两个标识位,leftdown和righup来分别表示当遍历到[i,j]时,下一个元素是在左下方还是右上方。这里有两种特殊情况,即当目前的遍历方向为右上时,当我们i=0时,我们只能往右走,而不能往右上走了,因为此时右上已经没有元素可以访问,而当j=n-1,即当前位置在最后一列时,只能往下走了。当目前的遍历方向为左下时,这种情况则分别对应为最后一行和第一列的情况,处理方法类似。
对于这种方法,具体参见如下代码:
void printMatrixZShape_1(int m, int n)
{
if(m <= 0 || n <= 0) return;
if(m == 1) //只有一行,按顺序输出改行即可
{
for(int j = 0; j < n; j++) cout << "0-" << j << endl;
return;
}
if(n == 1) //只有一列,按顺序输出该列即可
{
for(int i = 0; i < m; i++) cout << i << "-0" << endl;
return;
}
bool leftDown = true;
bool rightUp = false;
int i = 0, j = 0;
cout << i << "-" << j << endl;
i = 0, j = 1;
while(true)
{
cout << i << "-" << j << endl;
if(i == m-1 && j == n-1) return;
if(leftDown) //往左下方遍历矩阵
{
if(j == 0 || i == m-1) //此时无法继续往左下方走
{
if(i != m-1) i++; //当前位置在第一列,只能往下走
else j++; //当前位置在最后一行,只能往右走
rightUp = true; //改变下次遍历放下为右上
leftDown = false;
}
else
{
i++, j--;
}
}//if(leftDown)
else //往右上方遍历矩阵
{
if(i == 0 || j == n-1) //此时无法继续往右上方遍历
{
if(j != n-1) j++; //当前位置在第一行,只能往右走
else i++; //当前位置在最后一列,只能往下走
rightUp = false;
leftDown = true; //改变下次遍历的方向为左下
}
else
{
i--,j++;
}
}
}//while
}
解法二:
对于解法一,多少看上去觉得有点累赘。其实仔细观察一下,当我们处在位置[i,j]时,若i+j为偶数,则我们下一个元素在其右上方;而当i+j为奇数时,下一个元素在左下方。当然,这里也需要处理解法一中提到的特殊情况。
按照这种方法,代码则会变得更加清晰简洁:
void printMatrixZShape_2(int m, int n)
{
if(m <= 0 || n <= 0) return;
int i = 0, j = 0;
while(true)
{
cout << i << "-" << j << endl;
if(i == m-1 && j == n-1) return;
if((i+j)&0x1 != 0) //往左下方遍历矩阵
{
if(j == 0 || i == m-1) //此时无法继续往左下方走
{
if(i != m-1) i++; //当前位置在第一列,只能往下走
else j++; //当前位置在最后一行,只能往右走
}
else
{
i++, j--;
}
}//if(leftDown)
else //往右上方遍历矩阵
{
if(i == 0 || j == n-1) //此时无法继续往右上方遍历
{
if(j != n-1) j++; //当前位置在第一行,只能往右走
else i++; //当前位置在最后一列,只能往下走
}
else
{
i--,j++;
}
}
}//while
}