首頁 > 軟體

TypeScript順時針列印矩陣實現範例詳解

2022-09-04 18:03:16

前言

有一個矩陣,如何按照從外向裡以順時針的順序依次列印出每一個元素?本文將跟大家分享下這個演演算法,歡迎各位感興趣的開發者閱讀本文。

梳理思路

當我們遇到一個複雜的問題時,可以通過舉例將它畫出來,這樣就可以更直觀的發現規律。那麼我們就先構造一個矩陣出來,如下所示:

const matrix = [
  [1, 2, 3, 4],
  [5, 6, 7, 8],
  [9, 10, 11, 12],
  [13, 14, 15, 16]
];

順時針存取一個矩陣,那麼它的存取過程就如下圖所示:

觀察上圖後,我們可以很明顯的知道可以通過一個迴圈來列印這個矩陣,每次列印矩陣的一個圈,那麼迴圈的終止條件是什麼呢?

接下來,我們就來分析下回圈的終止條件。假設矩陣的行數為rows,列數為cols,列印第一圈的左上角座標是(0,0),第二圈的左上角座標是(1,1),以此類推,我們注意到左上角的座標中,行標與列標總是相同的,於是可以在矩陣中選取左上角為(start,start)的一圈作為我們的分析目標。

我們在來多列舉幾個例子觀察下,例如:

  • 對於5*5的矩陣而言,最後一圈只有1個數位,對應的座標為(2,2)
  • 對於6*6的矩陣而言,最後一圈有4個數位,其左上角的座標依然為(2,2)

距上所述,我們可以發現:5 > 2 * 26 > 2 * 2全部成立,於是可以得出讓迴圈終止的條件為:cols > start * 2 && rows > start * 2

接下來,我們來分析下如何實現列印一圈,前面的分析中我們已經知道了列印1圈需要4步,即:

  • 從左到右列印一行
  • 從上到下列印一列
  • 從右到左列印一行
  • 從下到上列印一列

每一步我們根據起始座標和終止座標用一個迴圈就能列印出一行或者一列,但是最後一圈有可能退化成只有一行、只有一列,甚至只有一個數位,因此列印這樣的一圈就不再需要四步。可能只需要三步、兩步甚至一步。

我們來分析下每一步的執行條件:

  • 第一步是必須的,因為列印一圈至少有一步
    • start作為行座標
    • 從start位置開始遍歷至終止列號,將其作為列座標
    • 輸出每一個元素

  • 第二步要求圈內至少有2行,即:終止行號大於起始行號
    • 從start+1位置遍歷至至終止行號,將其作為行座標
    • 終止列號作為列座標
    • 輸出每一個元素

  • 第三步要求圈內至少有兩行兩列,即:終止行號大於起始行號且終止列號大於起始列號
    • 從終止列號-1位置遍歷至start,將其作為列座標
    • 終止行號作為行座標
    • 輸出每一個元素

  • 第四步要求圈內至少有三行兩列,即:終止行號比起始行號至少大2,同時終止列號大於起始列號
    • 從終止行號-1位置遍歷至start+1位置,將其作為行座標
    • start作為列座標
    • 輸出每一個元素

實現程式碼

經過上面的分析,我們已經有了縝密的邏輯,接下來我們就可以愉快的進行編碼了,如下所示:

// 順時針列印矩陣
export function PrintMatrix<T>(
  matrix: Array<Array<T>>,
  cols: number,
  rows: number
): void {
  if (matrix == null || cols == null || rows == null) return;
  // 圈數
  let start = 0;
  while (cols > start * 2 && rows > start * 2) {
    // 列印每一圈的資料
    PrintMatrixInCircle(matrix, cols, rows, start);
    start++;
  }
}
// 列印矩陣的一圈
function PrintMatrixInCircle<T>(
  matrix: Array<Array<T>>,
  cols: number,
  rows: number,
  start: number
): void {
  // 計算當前圈結束點座標(索引從0開始,所以需要-1)
  // 終止列號
  const endX = cols - 1 - start;
  // 終止行號
  const endY = rows - 1 - start;
  // 從左到右列印一行
  for (let i = start; i <= endX; i++) {
    console.log(matrix[start][i]);
  }
  // 從上到下列印一列
  if (start < endY) {
    // 此時:
    //  最後一列已經在從左到右的列印中讀取了
    for (let i = start + 1; i <= endY; i++) {
      console.log(matrix[i][endX]);
    }
  }
  // 從右到左列印一行
  if (start < endX && start < endY) {
    // 此時:
    //  最後一列已經在從上到下的列印中讀取了
    for (let i = endX - 1; i >= start; i--) {
      console.log(matrix[endY][i]);
    }
  }
  // 從下到上列印一列
  if (start < endX && start < endY - 1) {
    // 此時:
    //  最後一列已經在從上到下的列印中讀取了
    //  第一列的列印已經在從左到右的列印中讀取了
    for (let i = endY - 1; i >= start + 1; i--) {
      console.log(matrix[i][start]);
    }
  }
}

我們用前面所舉的例子來驗證下上述程式碼能否正常執行,如下所示:

const matrix = [
  [1, 2, 3, 4],
  [5, 6, 7, 8],
  [9, 10, 11, 12],
  [13, 14, 15, 16]
];
PrintMatrix(matrix, 4, 4);

範例程式碼

本文所用程式碼完整版請移步:

PrintMatrix.ts

printMatrix-test.ts

以上就是TypeScript順時針列印矩陣實現範例詳解的詳細內容,更多關於TypeScript順時針列印矩陣的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com