計算 2d Java 陣列中對角線值的總和
1. 概述
在 Java 中使用二維數組(2D 數組)很常見,特別是對於涉及矩陣運算的任務。其中一項任務是計算二維數組中對角線值的總和。
在本教程中,我們將探索對二維數組中主對角線和次對角線的值求和的不同方法。
2.問題介紹
首先,讓我們快速了解一下問題。
二維數組形成矩陣。由於我們需要對角線上的元素求和,因此我們假設矩陣為n x n ,例如 4 x 4 2D 數組:
static final int[][] MATRIX = new int[][] {
 { 1, 2, 3, 4 },
 { 5, 6, 7, 8 },
 { 9, 10, 11, 12 },
 { 13, 14, 15, 100 }
 };接下來,讓我們澄清一下主對角線和次對角線的含義:
- 主對角線 -對角線從矩陣的左上角延伸到右下角。例如,在上例中,主對角線上的元素為 1、6、11 和 100
- 次對角線 –對角線從右上角延伸到左下角。在同一例子中,4、7、10 和 13 屬於次對角線。
兩條對角線值的總和如下:
static final int SUM_MAIN_DIAGONAL = 118; //1+6+11+100
 static final int SUM_SECONDARY_DIAGONAL = 34; //4+7+10+13由於我們想要建立方法來涵蓋兩種對角線類型,因此讓我們為它們建立一個Enum :
enum DiagonalType {
 Main, Secondary
 }稍後,我們可以將DiagonalType傳遞給我們的解決方案方法來獲得相應的結果。
3. 辨識對角線上的元素
要計算對角線值的總和,我們必須先辨識對角線上的那些元素。在主對角線的情況下,它非常簡單。當元素的行索引 ( rowIdx ) 和列索引 ( colIdx ) 相等時,此元素位於主對角線上,例如MATRIX[0][0] = 1, MATRIX[1][1] = 6,以及MATRIX[3][3] = 100 。
另一方面,給定一個n x n矩陣,如果一個元素位於次對角線上,則rowIdx + colIdx = n – 1. , MATRIX[0][3] = 4 (0 + 3 = 4 -1), MATRIX[1][2] = 7 (1 + 2 = 4 – 1), MATRIX[3][0] = 13 (3 + 0 = 4 -1 ) 。因此,我們有**colIdx = n – rowIdx – 1** 。
現在我們了解了對角線元素的規則,讓我們建立計算總和的方法。
4. 循環方法
一個簡單的方法是根據所需的對角線類型循環遍歷行索引,並對元素求和:
int diagonalSumBySingleLoop(int[][] matrix, DiagonalType diagonalType) {
 int sum = 0;
 int n = matrix.length;
 for (int rowIdx = 0; rowIdx < n; row++) {
 int colIdx = diagonalType == Main ? rowIdx : n - rowIdx - 1;
 sum += matrix[rowIdx][colIdx];
 }
 return sum;
 }正如我們在上面的實作中所看到的,我們根據給定的diagonalType計算所需的colIdx ,然後將rowIdx和colIdx上的元素新增到sum變數中。
接下來,我們來測試這個解決方案是否能產生預期的結果:
assertEquals(SUM_MAIN_DIAGONAL, diagonalSumBySingleLoop(MATRIX, Main));
 assertEquals(SUM_SECONDARY_DIAGONAL, diagonalSumBySingleLoop(MATRIX, Secondary));事實證明,該方法對兩種對角線類型的正確值求和。
5. 帶有IntBinaryOperator物件的DiagonalType
基於循環的解決方案很簡單。然而,在每個循環步驟中,我們必須檢查diagonalType實例以確定colIdx ,儘管diagonalType是循環期間不會改變的參數。
接下來,讓我們看看是否可以改進一下。
一種想法是為每個DiagonalType實例分配一個IntBinaryOperator對象,以便我們可以計算colIdx而無需檢查我們擁有哪種對角線類型:
enum DiagonalType {
 Main((rowIdx, len) -> rowIdx),
 Secondary((rowIdx, len) -> (len - rowIdx - 1));
 public final IntBinaryOperator colIdxOp;
 DiagonalType(IntBinaryOperator colIdxOp) {
 this.colIdxOp = colIdxOp;
 }
 }如上面的程式碼所示,我們在DiagonalType Enum加入了一個IntBinaryOperator屬性。 **IntBinaryOperation**是一個函數接口,它接受兩個int參數並產生一個int結果。在此範例中,我們使用兩個 lambda 表達式作為Enum實例的IntBinaryOperator物件。
現在,我們可以刪除for迴圈中對角線類型檢查的三元運算:
int diagonalSumFunctional(int[][] matrix, DiagonalType diagonalType) {
 int sum = 0;
 int n = matrix.length;
 for (int rowIdx = 0; rowIdx < n; row++) {
 sum += matrix[rowIdx][diagonalType.colIdxOp.applyAsInt(rowIdx, n)];
 }
 return sum;
 }正如我們所看到的,我們可以透過呼叫applyAsInt()直接呼叫diagonalType的colIdxOp函數來取得所需的**colIdx** .
當然,測試仍然通過:
assertEquals(SUM_MAIN_DIAGONAL, diagonalSumFunctional(MATRIX, Main));
 assertEquals(SUM_SECONDARY_DIAGONAL, diagonalSumFunctional(MATRIX, Secondary));6. 使用串流API
Java 8 中引進了函數式介面。接下來,讓我們使用這兩個 Java 8 功能來解決問題:
public int diagonalSumFunctionalByStream(int[][] matrix, DiagonalType diagonalType) {
 int n = matrix.length;
 return IntStream.range(0, n)
 .map(i -> MATRIX[i][diagonalType.colIdxOp.applyAsInt(i, n)])
 .sum();
 }在此範例中,我們將 for 迴圈替換為**IntStream.range()** .另外, map()負責將每個索引 ( i ) 轉換為對角線上所需的元素。然後, sum()產生結果。
最後,這個解決方案也通過了測試:
assertEquals(SUM_MAIN_DIAGONAL, diagonalSumFunctionalByStream(MATRIX, Main));
 assertEquals(SUM_SECONDARY_DIAGONAL, diagonalSumFunctionalByStream(MATRIX, Secondary));與最初的基於循環的解決方案相比,這種方法更加流暢且更易於閱讀。
七、結論
在本文中,我們探討了計算 2D Java 陣列中對角線值總和的不同方法。了解主對角線和次對角線的索引是解決問題的關鍵。
與往常一樣,範例的完整原始程式碼可在 GitHub 上取得。