數組問題:給定一個含有 M x N 個元素的矩陣(M 行,N 列),請以對角線遍歷的順序返回這個矩陣中的所有元素,對角線遍歷如下圖所示。
示例:
[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]
輸出: [1,2,4,7,5,3,6,8,9]
說明:給定矩陣中的元素總數不會超過 100000 。
思路:對於對角線上的元素,仔細觀察可以發現規律,如果我們設行和列對應的下標是m和n,對角線上的元素向上走是m--,n++
向下走是m++,n--;
根據元素的索引的座標和(數組元素的兩個下標和)我們可以發現一些規律:和爲偶數像上遍歷,和爲奇數向下遍歷。
下標和爲偶數時,如果到了第一行就讓列加1向右移動,如果到了最後一列就讓行加1向下移動。
下標和爲奇數時:如果到了第一列就讓行加1向下移動,如果到了最後一行就讓列加1向右移動。
這樣完成對角的轉換。
所以綜合上面的分析可以得到結果:
public int[] findDiagonalOrder(int[][] matrix) {
if (matrix == null) {
return null;
}
if (matrix.length == 0) {
int result[] = {};
return result;
}
int m = matrix.length;
int n = matrix[0].length;
int r = 0;
int c = 0;
int result[] = new int[m * n];
for (int i = 0; i < result.length; i++) {
result[i] = matrix[r][c];
if ((r + c) % 2 == 0) {
if (r == 0) {//元素在第一行,往右
c++;
} else if (c == (n - 1)) {
r++;//往下
} else {//其他情況
r--;
c++;
}
} else {//索引和是奇數
if (c == 0) {//第一列
r++;//往下走
} else if (r == (m - 1)) {//最後一行
c++;//往右走
} else {
r++;//行
c--;//列
}
}
}
return result;
}
對於以上代碼輸入數據{{1, 2, 3},{4, 5, 6},{7, 8, 9}}異常提示:
debug發現:對於上面的代碼:對於下標和是偶數的元素3,由於先判斷了元素在第一行就會向右導致列索引加1越界;同樣對於最後一列的最後一行也可能出現數組越界。因此修改這兩個地方的判斷順序。
最後結果如下:
public int[] findDiagonalOrder(int[][] matrix) {
if (matrix == null) {
return null;
}
if (matrix.length == 0) {
int result[] = {};
return result;
}
int m = matrix.length;
int n = matrix[0].length;
int r = 0;
int c = 0;
int result[] = new int[m * n];
for (int i = 0; i < result.length; i++) {
result[i] = matrix[r][c];
if ((r + c) % 2 == 0) {
if (c == (n - 1)) {//元素在最後一列(最後一列要先判斷)
r++;//往下
} else if (r == 0) {//元素在第一行,往右
c++;
} else {//其他情況
r--;
c++;
}
} else {//索引和是奇數
if (r == (m - 1)) {//最後一行
c++;//往右走
} else if (c == 0) {//第一列
r++;//往下走
} else {
r++;//行
c--;//列
}
}
}
return result;
}
輸出結果:
輸入數據:
int matric[][] = {{1, 2, 3,10}, {4, 5, 6,11}, {7, 8, 9,12}};
輸出結果:
總結:對於數組的問題,不會有其他的操作,找出下標變換的規律是關鍵;同時要處理好下標變換的邊界。