1. 程式人生 > >498#對角線遍歷

498#對角線遍歷

find 思路 pre nal system 再次 void lse 方法

題目描述

給定一個含有 M x N 個元素的矩陣(M行,N列),請以對角線遍歷的順序返回這個矩陣中的所有元素,對角線遍歷如下圖所示。

示例:

輸入:
[
 [ 1, 2, 3 ],
 [ 4, 5, 6 ],
 [ 7, 8, 9 ]
]
輸出:  [1,2,4,7,5,3,6,8,9]

說明:

  1. 給定矩陣中的元素總數不會超過 100000 。

分析

分析一下遍歷順序的特點,可以看出,對角線的方向跟索引和(行的索引值+列的索引值)的奇偶性有關,然後加上邊界情況,遍歷的路線大概就出來了。

具體可以分為以下幾種情況:

  1. 索引和為偶數:
    • 元素在第一行,往右走
    • 元素在最後一列,往下走
    • 其他情況,往右上走
  2. 索引和為奇數:
    • 元素在第一列,往下走
    • 元素在最後一行,往右走
    • 其他情況,往左下走

按照這個思路,寫出的方法如下:

public class DiagonalTraverse {
    public int[] findDiagonalOrder(int[][] matrix)
    {
        if (matrix.length == 0) return new int[0];
        int m = matrix.length;      // 待處理的矩陣有M行、N列
        int n = matrix[0].length;
        int[] result = new int[m * n];  // 用來存放遍歷的結果
        int r = 0;
        int c = 0;
        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;
    }
}

測試用例

public static void main(String[] args)
{
    DiagonalTraverse dt = new DiagonalTraverse();
    int[][] a = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
    int[] b = dt.findDiagonalOrder(a);
    System.out.println(Arrays.toString(b));
}

運行以下,發現出錯了,報的是數組索引越界了

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3

用IDE單步執行調試發現,問題出在邊界的元素上,比如這個例子中的元素3,它的索引和是偶數,在第一行,最後一列,在程序的判斷流程中,會先判定它在第一行,所以就會往右走,數組索引就越界了。同理,最左下角(第一列,最後一行)的那個元素同樣有這種越界的隱患,需要將相應的判斷語句的順序調整一下。

修改後判斷流程如下:

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--;
    }
}

再次測試,可以通過了。

498#對角線遍歷