1. 程式人生 > 實用技巧 >劍指19.順時針列印矩陣

劍指19.順時針列印矩陣

題目描述

輸入一個矩陣,按照從外向裡以順時針的順序依次打印出每一個數字,例如,如果輸入如下4 X 4矩陣: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 則依次打印出數字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.

思路

這道題沒有很巧妙的演算法可以解決,就是需要仔細分析每一步的邊界條件。畫圖之後很容易發現可以把矩陣分解成若干個圓圈,然後從外向內列印每個圓圈。我們可以把列印一圈分為四步,每一步根據起始座標和終止座標用一個迴圈就能打印出一行或者一列。
  • 第一步:從左到右列印一行;
  • 第二步:從上到下列印一列;
  • 第三步:從右到左列印一行;
  • 第四步:從下到上列印一列。
需要注意的是,最後一圈有可能退化為只有一行,只有一列,或者只有一個數字。因此要仔細分析列印時每一步的前提條件。

解法1

import java.util.ArrayList;
import java.lang.Math;
public class Solution {
    public ArrayList<Integer> printMatrix(int [][] matrix) {
        ArrayList<Integer> ans = new ArrayList<>();
        // 計算行數和列數
int row = matrix.length; int col = matrix[0].length; // 初始化邊界 int c1 = 0, c2 = col - 1; // 列邊界 int r1 = 0, r2 = row - 1; // 行邊界 //計算輸入的矩陣一共需要列印幾圈,行列最小值 / 2,如果是奇數還需要加上1 int times = (Math.min(row,col) & 1) == 0 ? Math.min(row,col) / 2 : (Math.min(row,col) / 2) + 1;
for (int time = 0; time < times; time++){ // for (int i = c1; i <= c2; i++) ans.add(matrix[r1][i]); // for (int i = r1 + 1; i <= r2; i++) ans.add(matrix[i][c2]); // 考慮邊界,例如只有一行(r1=r2),只有一列(c1=c2);如果不加限制,會重複向左列印或者重複向上列印 if (c1 != c2 && r1 != r2){ // 或者 if (c1 < c2 && r1 < r2) // for (int i = c2 - 1; i >= c1; i--) ans.add(matrix[r2][i]); // for (int i = r2 - 1; i > r1; i--) ans.add(matrix[i][c1]); } // 每經過一圈後更新上下左右的邊界 c1++; c2--; r1++; r2--; } return ans; } }

本地測試案例

        int[][] arr = new int[][]{{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}}; //常規例子
        int[][] arr = new int[][]{{1}}; // 只有一行一列
        int[][] arr = new int[][]{{1,2,3,4,5},{6,7,8,9,10},{11,12,13,14,15},{16,17,18,19,20},{21,22,23,24,25}}; // 最後一圈只有一個數字
        int[][] arr = new int[][]{{1},{2},{3},{4},{5}}; // 只有一列
        int[][] arr = new int[][]{{1,2,3,4}}; // 只有一行