Mục lục bài họcĐang ở d04-b3
← AP Computer Science A
0/16 bài đã học xong
Chương 4 · Unit 4 — Data Collections · Bài 3/4 của chương · bài 15/16 của AP Computer Science A

Two-Dimensional Arrays

Mảng hai chiều
← Mục lục bài học
Lý thuyết · English

An array of arrays

In Java a 2D array is really an array whose elements are arrays. For int[][] g = new int[3][4];:

g.length        →  3    number of ROWS
g[0].length     →  4    number of COLUMNS in row 0
g[r][c]         →  element at row r, column c

The first index is always the row. On the AP exam all 2D arrays are rectangular, so every row has the same length and g[0].length is a safe column count — but writing g[r].length in the inner loop is always correct and costs nothing.

Row-major traversal

for (int r = 0; r < g.length; r++) {
    for (int c = 0; c < g[r].length; c++) {
        System.out.print(g[r][c]);
    }
}

for (int[] row : g) {          // each row is an int[]
    for (int v : row) {        // each v is an int
        System.out.print(v);
    }
}

Swapping the two loop headers gives column-major order, which visits the same cells in a different order — the difference matters as soon as you print, or stop early.

Giải thích tiếng Việt

Mảng hai chiều là mảng của những mảng. Với int[][] g = new int[3][4]; thì g.lengthsố hàng (3) và g[0].lengthsố cột (4). Chỉ số đầu luôn luôn là hàng: g[r][c] đọc là “hàng r, cột c”. Đảo hai chỉ số vẫn biên dịch được nếu số hàng và số cột bằng nhau, nên đây là loại lỗi chỉ lộ ra ở kết quả sai chứ không ở màn hình đỏ.

Duyệt theo hàng là mặc định: vòng ngoài chạy hàng, vòng trong chạy cột. Đổi chỗ hai vòng lặp thì thành duyệt theo cột — vẫn thăm đủ mọi ô, nhưng thứ tự khác. Thứ tự chỉ vô hại khi ta cộng dồn tất cả; hễ có in ra, có dừng sớm, hay có ghi vào một mảng khác, thứ tự lập tức thành nội dung của câu trả lời.

Vòng for-each lồng nhau viết ngắn hơn nhưng phải khai đúng kiểu: vòng ngoài lấy ra một int[] (nguyên một hàng), vòng trong mới lấy ra int. Dạng này chỉ để đọc — muốn ghi vào ô, hoặc muốn biết mình đang ở hàng nào cột nào, thì bắt buộc quay về vòng lặp có chỉ số.

Đề AP luôn cho mảng chữ nhật (mọi hàng dài bằng nhau), nhưng viết g[r].length ở vòng trong thì không bao giờ sai, kể cả với mảng răng cưa.

int[][] g = new int[3][4]; g.length = 3 g[0].length = 4 hàng cột 0 cột 1 cột 2 cột 3 g[0][0] g[0][1] g[0][2] g[0][3] g[1][0] g[1][1] g[1][2] g[1][3] g[2][0] g[2][1] g[2][2] g[2][3] 0 1 2 duyệt theo hàng (row-major): hàng ngoài, cột trong g[hàng][cột] — chỉ số ĐẦU là hàng, luôn luôn
Đọc nhãn ô là đủ để không lẫn. Mọi ô trên cùng một hàng có chỉ số đầu giống nhau; mọi ô trên cùng một cột có chỉ số sau giống nhau. Khi đề hỏi “tổng của cột 2”, vòng lặp phải chạy biến hàng và giữ nguyên số 2 ở vị trí thứ hai: g[r][2]. Viết nhầm thành g[2][c] là đang cộng hàng 2 — hai kết quả đều là số hợp lệ, nên không có gì báo cho ta biết là đã lấy nhầm.
Ví dụ — tổng từng cột

Viết phương thức trả về mảng một chiều chứa tổng của từng cột trong mảng hai chiều chữ nhật int[][] g.

Giải.
public static int[] tongCot(int[][] g) {
    int[] kq = new int[g[0].length];      // dài bằng SỐ CỘT
    for (int c = 0; c < g[0].length; c++) {
        for (int r = 0; r < g.length; r++) {
            kq[c] += g[r][c];
        }
    }
    return kq;
}

Ba chỗ dễ sai, xử lý từng chỗ. Một: độ dài mảng kết quả là số cột g[0].length, không phải số hàng — có bao nhiêu cột thì có bấy nhiêu tổng. Hai: bên trong phải là g[r][c], giữ nguyên thứ tự hàng-cột dù vòng ngoài đang chạy cột. Ba: kq mới tạo đã được điền sẵn số 0, nên cộng dồn thẳng vào là an toàn, không cần gán khởi tạo.

Với {{1,2,3},{4,5,6},{7,8,9}} phương thức trả về {12, 15, 18}.

Bẫy hay mất điểm — Bẫy chết người của mảng hai chiều là đảo hai chỉ số: viết g[c][r] thay vì g[r][c]. Với mảng vuông nó chạy trơn tru và trả về một con số trông rất hợp lý, nên không ai phát hiện cho tới lúc chấm. Cách chặn: đặt tên biến lặp là rc chứ đừng dùng i, j — mắt nhìn g[c][r] sẽ thấy sai ngay, còn nhìn g[j][i] thì không. Bẫy thứ hai: dùng g.length làm số cột. Nhớ một câu — g.length đếm hàng, thêm một cặp ngoặc vuông mới ra cột.
Phải nhớ — Chỉ số đầu là hàng, g.length là số hàng, g[0].length là số cột. Duyệt theo hàng là mặc định; đảo hai vòng lặp là đổi thứ tự thăm chứ không đổi tập hợp ô được thăm.

Đọc xong rồi — làm thử ngay

Bài tập của chương Unit 4 — Data Collections gồm 14 câu trắc nghiệm và 8 đề tự luận. Đáp án hiện ngay khi chọn, miễn phí.

Làm bài tập chương →