An interviewer asked me to write clean Java code for clockwise and counterclockwise spiral matrix traversal.
e.g. {{1,2,3}, {7,8,9}}
becomes {1,2,3,9,8,7}
and {1,7,8,9,3,2}
I've tried many methods and wrote down the below code while keeping in mind that it should be as clean as possible. But I am not sure it is the right answer. Please evaluate it.
Note: I've removed comments and test cases to reduce text size.
public abstract class MatrixTraverse {
private TraverseDirection traverseDirection;
private int matrixCount;
private int row;
private int upLimit;
private int col;
private int downLimit;
private int leftLimit;
private int rightLimit;
public abstract void traverseUp();
public abstract void traverseLeft();
public abstract void traverseDown();
public abstract void traverseRight();
public MatrixTraverse(final TraverseDirection traverseDirection) {
this.traverseDirection = traverseDirection;
}
public void init(int[][] matrix) {
final int rowSize = matrix.length;
final int colSize = matrix[0].length;
upLimit = 0;
downLimit = matrix.length - 1;
leftLimit = 0;
rightLimit = matrix[0].length - 1;
matrixCount = rowSize * colSize;
row = 0;
col = 0;
}
public int[] traverseMatrix(int[][] matrix) {
init(matrix);
final int[] retTraveserdMatrix = new int[matrixCount];
for (int index = 0; index < matrixCount; index++) {
retTraveserdMatrix[index] = matrix[row][col];
switch (traverseDirection) {
case RIGHT :
traverseRight();
break;
case DOWN :
traverseDown();
break;
case LEFT :
traverseLeft();
break;
case UP :
traverseUp();
break;
default :
break;
}
}
return retTraveserdMatrix;
}
protected void moveDown() {
traverseDirection = TraverseDirection.DOWN;
}
public void moveRight() {
traverseDirection = TraverseDirection.RIGHT;
}
protected void moveLeft() {
traverseDirection = TraverseDirection.LEFT;
}
protected void moveUp() {
traverseDirection = TraverseDirection.UP;
}
public void decrementRow() {
--row;
}
public boolean isUpLimitExceed() {
return (row < upLimit);
}
public void incrementLeftLimit() {
++leftLimit;
}
public void incrementCol() {
++col;
}
public void incrementRow() {
++row;
}
public boolean isLeftLimitExceed() {
return (col < leftLimit);
}
public void decrementCol() {
--col;
}
public void decrementDownLimit() {
--downLimit;
}
public void decrementRightLimit() {
--rightLimit;
}
public boolean isDownLimitExceed() {
return (row > downLimit);
}
public boolean isRightLimitExceed() {
return (col > rightLimit);
}
public void incrementUpLimit() {
++upLimit;
}
}
public class MatrixTraverseClock extends MatrixTraverse {
public MatrixTraverseClock() {
super(TraverseDirection.RIGHT);
}
public void traverseUp() {
decrementRow();
if (isUpLimitExceed()) {
incrementRow();
incrementCol();
incrementLeftLimit();
moveRight();
}
}
public void traverseLeft() {
decrementCol();
if (isLeftLimitExceed()) {
incrementCol();
decrementRow();
decrementDownLimit();
moveUp();
}
}
public void traverseDown() {
incrementRow();
if (isDownLimitExceed()) {
decrementRow();
decrementCol();
decrementRightLimit();
moveLeft();
}
}
public void traverseRight() {
incrementCol();
if (isRightLimitExceed()) {
decrementCol();
incrementRow();
incrementUpLimit();
moveDown();
}
}
}
public class MatrixTraverseCounterClock extends MatrixTraverse {
public MatrixTraverseCounterClock() {
super(TraverseDirection.DOWN);
}
public void traverseUp() {
decrementRow();
if (isUpLimitExceed()) {
incrementRow();
decrementCol();
decrementRightLimit();
moveLeft();
}
}
public void traverseLeft() {
decrementCol();
if (isLeftLimitExceed()) {
incrementCol();
incrementRow();
incrementUpLimit();
moveDown();
}
}
public void traverseDown() {
incrementRow();
if (isDownLimitExceed()) {
decrementRow();
incrementCol();
incrementLeftLimit();
moveRight();
}
}
public void traverseRight() {
incrementCol();
if (isRightLimitExceed()) {
decrementCol();
decrementRow();
decrementDownLimit();
moveUp();
}
}
}
For Testing
final int[][] inputMatrix = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
final int[] expectedResult = {1, 2, 3, 6, 9, 8, 7, 4, 5};
final MatrixTraverse matrixTraverse = new MatrixTraverseClock();
Assert.assertArrayEquals(expectedResult,
matrixTraverse.traverseMatrix(inputMatrix));
final int[] expectedResult1 = {1, 4, 7, 8, 9, 6, 3, 2, 5};
final MatrixTraverse matrixTraverse = new MatrixTraverseCounterClock();
Assert.assertArrayEquals(expectedResult1,
matrixTraverse.traverseMatrix(inputMatrix));