我有一些代码(following this example)从左上角开始遍历矩阵并顺时针方向移动。我想在此基础上制作三种新方法:
为了解决这些问题,我需要更改哪些内容?我试过反转计数器增量并改变开始/结束行/列没有成功。
public static void traverseSpiral(int[][] matrix) {
if(matrix.length == 0|| matrix[0].length == 0) {
return;
}
StringBuffer stringBuffer = new StringBuffer();
int counter = matrix.length * matrix[0].length;
int startRow = 0;
int endRow = matrix.length-1;
int startCol = 0;
int endCol = matrix[0].length-1;
boolean moveCol = true;
boolean leftToRight = true;
boolean upDown = true;
while(counter>0) {
if(moveCol) {
if(leftToRight) {
/* printing entire row left to right */
for(int i = startCol; i <= endCol ; i++){
stringBuffer.append(matrix[startRow][i]);
counter--;
}
leftToRight = false;
moveCol = false;
startRow++;
}
else{
/* printing entire row right to left */
for(int i = endCol ; i >= startCol ; i--){
stringBuffer.append(matrix[endRow][i]);
counter--;
}
leftToRight = true;
moveCol = false;
endRow--;
}
}
else
{
if(upDown){
/* printing column up down */
for(int i = startRow ; i <= endRow ; i++){
stringBuffer.append(matrix[i][endCol]);
counter--;
}
upDown = false;
moveCol = true;
endCol--;
}
else
{
/* printing entire col down up */
for(int i = endRow ; i >= startRow ; i--){
stringBuffer.append(matrix[i][startCol]);
counter--;
}
upDown = true;
moveCol = true;
startCol++;
}
}
}
System.out.println(stringBuffer.toString());
}
答案 0 :(得分:2)
您的代码的问题在于您将其全部转储到一个方法中,使您的代码非常难以阅读并且更难以修改(不会破坏任何内容)。
由于这是针对面试问题,您应该努力不仅找到解决方案,而且找到最优雅的解决方案。或者最快的解决方案。或者最短的。最终,每个程序员在代码方面都有不同的优先级。但大多数(如果不是所有程序员)都努力编写好的代码。
优秀代码易于阅读,编写和维护。虽然没有关于什么是优秀代码的确切定义,但克里斯托弗·约翰逊发布了this answer,我认为它能够很好地涵盖基本要素。
考虑将代码分解为单独的方法,每个方法都有自己的责任。马上,我可以看到四个代码块应该是他们自己的方法(从左到右,从右到左,从上到下,从下到上打印)。这将使您的代码更清晰。
例如,在这个问题的递归解决方案中,我至少有5个方法:
// A method that will handle the traversal of the spiral.
public static String clockwise(int[][] matrix);
// Responsible for printing a column from bottom to top.
public static String up(int[][] matrix, int first, int last);
// Responsible for printing a column from top to bottom.
public static String down(int[][] matrix, int first, int last);
// Responsible for printing a column from right to left.
public static String left(int[][] matrix, int first, int last);
// Responsible for printing a column from left to right.
public static String right(int[][] matrix, int first, int last);
使用这些方法,实现一种逆时针遍历相同螺旋的方法就像编写另一种重用up(matrix, first, last)
,down(matrix, first, last)
,left(matrix, first, last)
&amp;的代码的方法一样简单。 right(matrix, first, last)
因为:
Clockwise = right, down, left, up;
Counter-Clockwise = down, right, up, left;
就个人而言,我更喜欢divide-and-conquer递归方法。由于在大小为3x3
的网格周围进行螺旋形旋转与在2x2
的网格周围进行一次额外一圈的旋转基本相同,因此您可以使用递归来查找&amp;解决问题的最小版本,并按步骤构建解决方案。
我强烈建议你研究一下递归和分数&amp;独立征服方法。如果您只是对解决螺旋遍历问题感兴趣,包括顺时针,逆时针,顺时针向外和逆时针向外,请参阅GitHub Gist here。
注意:上面的代码是原样,不保证任何种类。所以请注意。
答案 1 :(得分:1)
需要实现三种方法:
从左上角开始逆时针方向
从中间开始顺时针方向
从中间开始并逆时针走的
让我们谈谈第一个(你实现它)
我们采用3x3矩阵
+---+---+---+
| | | |
+---+---+---+
| | | |
+---+---+---+
| | | |
+---+---+---+
因此,对于您的实现,它应该是
SR=0, ER=2, SC=0, EC=2
(SR: startRow, ER: endRow, SC: startCol, EC: endCol)
SC->EC
SR++ (=>SR=1)
SR->ER
EC-- (=>EC=1)
EC->SC
ER-- (=>ER=1)
ER->SR
SC++ (=>SC=1)
SC->EC
-> finish with (SR=1,ER=1,SC=1,EC=1)
让我们扭转它,所以它成为第三个。
SR=1, ER=1, SC=1, EC=1
EC->SC
SC--
SR->ER
ER++
SC->EC
EC++
ER->SR
SR--
EC->SC
-> finish with (SR=0,ER=2,SC=0,EC=2)
因此,重点不仅要改变SR,ER,SC,EC的值,还要改变修改其值的位置。
一切都是颠倒的,所以向右走,即打印startCol
就会打印endCol
。其他方向相同。
因此,
if(leftToRight) {
/* printing entire row left to right */
for(int i = startCol; i <= endCol ; i++){
stringBuffer.append(matrix[startRow][i]);
counter--;
}
leftToRight = false;
moveCol = false;
startRow++;
}
成为
if (leftToRight) {
/* printing entire row left to right */
for (int i = startCol; i <= endCol; i++) {
stringBuffer.append(matrix[endRow][i]);
counter--;
}
leftToRight = false;
moveCol = false;
endCol++;
}
其行#和列#为奇数的矩阵,您可以选择由(moveCol,leftRight,upDown)定义的任何起始方向。然而,矩阵的行#或列#是偶数,那么起始方向是显着的。
+---+---+---+---+
| | | | |
+---+---+---+---+
| | P | | |
+---+---+---+---+
| | | | |
+---+---+---+---+
| | | | |
+---+---+---+---+
例如,对于4x4矩阵,如果起点是P(1,1)(startRow =(4-1)/ 2,startCol =(4-1)/ 2),那么只有一种方法可以进行螺旋运算逆时针(upDown = true,leftRight = true,moveCol = false)
类似的方法可以应用于第二个问题
if (leftToRight) {
/* printing entire row left to right */
for (int i = startCol; i <= endCol; i++) {
stringBuffer.append(matrix[startRow][i]);
counter--;
}
leftToRight = false;
moveCol = false;
endCol++;
}
答案 2 :(得分:0)
这很简单,请参阅下面的解决方案:
class Region {
int left, right, top, bottom;
Region(int _left, int _right, int _top, int_bottom) {
left=_left; right=_right; top=_top; bottom=_bottom;
}
boolean isEmpty() { return (left>right || top>bottom); }
boolean isSingleElement() { return (left==right && top==bottom); }
}
List<Coordinate> traverseClockWise(Region r) {
List<Coordinate> l = new List<Coordinate>();
if (r.isEmpty()) {
return l;
}
if (r.isSingleElement()) {
l.add(new Coordinate(r.left, r.top));
return l;
}
for (int i=r.left; i<r.right; i++) {
l.add(new Coordinate(i, r.top));
}
for (int i=r.top; i<r.bottom; i++) {
l.add(new Coordinate(r.right, i));
}
for (int i=r.right; i>r.left; i--) {
l.add(new Coordinate(i, r.bottom));
}
for (int i=r.bottom; i>r.top; i--) {
l.add(new Coordinate(r.left, i));
}
l.addAll(traverseClockWise(new Region(r.left+1, r.right-1, r.top+1, rs.bottom-1)));
return l;
}
void traverse(Matrix A, int row, int col) {
}
void example() {
//suppose A is the matrix you are given and n is the size of the matrix
Matrix A = new Matrix(n,n);
List<Coordinates> l = traverseClockWise(new Region(1, n, 1, n));
// to traverse it from top left counterclockwise
for (int i=0; i<l.size(); i++) {
traverse(A, l[i].col, l[i].row);
}
// to traverse it from the middle and clockwise
for (int i=l.size()-1; i>=0; i--) {
traverse(A, l[i].col, l[i].row);
}
// to traverse it from the middle and counterclockwise
for (int i=l.size()-1; i>=0; i--) {
traverse(A, l[i].row, l[i].col);
}
}