Hướng dẫn giải của In mảng 2 chiều dạng bảng
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.
Lời giải này đang bị ẩn cho đến khi bạn chọn mở ra.
Chúng tôi khuyên bạn nên tự thử giải bài trước. Việc mở lời giải có thể làm lộ mất ý tưởng chính trước khi bạn có cơ hội tự giải.
Bạn phải đăng nhập để mở lời giải này.
Đăng nhậpTác giả: , , ,
Hiểu bài toán
Bài toán yêu cầu nhập một mảng 2 chiều gồm các số nguyên có kích thước m dòng và n cột từ bàn phím, sau đó in ra mảng đó dưới dạng bảng. Các phần tử trên cùng một dòng được ngăn cách bởi dấu cách. Dòng đầu tiên của input chứa hai số nguyên m và n. Dòng thứ hai chứa m * n số nguyên là các phần tử của mảng, được nhập theo thứ tự từng dòng (dòng 1 từ trái sang phải, rồi đến dòng 2, v.v.).
Các cách tiếp cận
Cách Sử dụng mảng tĩnh với kích thước tối đa
#include <stdio.h>
int main(void) {
int a[10][10];
int n, m;
scanf("%d%d", &n, &m);
int i, j;
for (i = 0; i < n; i++){
for (j = 0; j < m; j++){
scanf("%d", &a[i][j]);
}
}
for (i = 0; i < n; i++){
for (j = 0; j < m; j++){
printf("%d ", a[i][j]);
}
printf("\n");
}
return 0;
}
- Time Complexity: O(m * n)
- Space Complexity: O(1) (kích thước cố định)
Đây là cách tiếp cận truyền thống và đơn giản nhất. Khai báo mảng 2 chiều với kích thước cố định lớn hơn hoặc bằng giới hạn tối đa của đề bài (ví dụ a[10][10]). Sử dụng hai vòng lặp lồng nhau để đọc dữ liệu vào các phần tử của mảng và sau đó in ra. Biến n và m lần lượt là số dòng và số cột.
Cách Sử dụng mảng biến (VLA) trong C
#include <stdio.h>
int main() {
int m, n;
scanf("%d%d", &m, &n);
int a[m][n];
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
scanf("%d", &a[i][j]);
}
}
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
printf("%d ", a[i][j]);
}
printf("\n");
}
return 0;
}
- Time Complexity: O(m * n)
- Space Complexity: O(m * n)
Cách tiếp cận này sử dụng Variable Length Arrays (VLA), một tính năng của C99 cho phép khai báo mảng với kích thước xác định trong thời gian chạy. Kích thước mảng a[m][n] được cấp phát động trên stack dựa trên giá trị m và n nhập vào. Điều này giúp tiết kiệm bộ nhớ hơn so với mảng tĩnh lớn (nếu m, n nhỏ) và linh hoạt hơn.
Cách Sử dụng mảng tĩnh với kích thước lớn (Thư viện)
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <limits.h>
int main()
{
int n,m,a[15][15];
scanf("%d %d",&m,&n);
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++) scanf("%d",&a[i][j]);
}
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++) printf("%d ",a[i][j]);
printf("\n");
}
return 0;
}
- Time Complexity: O(m * n)
- Space Complexity: O(1)
Cách tiếp cận này tương tự như cách đầu tiên nhưng khai báo mảng với kích thước là 15x15, lớn hơn một chút so với giới hạn đề bài (10x10). Việc khai báo các thư viện như math.h, string.h, limits.h tuy không cần thiết cho bài toán này nhưng không ảnh hưởng đến logic chính. Logic vòng lặp vẫn là O(m*n).
Phân tích độ phức tạp
| Cách tiếp cận | Time | Space | Tên |
|---|---|---|---|
| 1 | O(m * n) | O(1) (kích thước cố định) | Sử dụng mảng tĩnh với kích thước tối đa |
| 2 | O(m * n) | O(m * n) | Sử dụng mảng biến (VLA) trong C |
| 3 | O(m * n) | O(1) | Sử dụng mảng tĩnh với kích thước lớn (Thư viện) |
Bài học kinh nghiệm
- Vấn đề cốt lõi là thao tác nhập/xuất cơ bản với mảng 2 chiều.
- Thứ tự duyệt mảng: Dòng ngoài cùng (i) chạy từ 0 đến m-1, dòng trong cùng (j) chạy từ 0 đến n-1 để đảm bảo in đúng thứ tự hàng và cột.
Lỗi thường gặp
- Lưu ý thứ tự khai báo biến trong
scanfvà vòng lặp:mthường là số dòng,nlà số cột. Cần đảm bảo vòng lặp lồng đúng (vòng lặp ngoài cho dòng, vòng lặp trong cho cột). - Đoạn in ra (printf) thường in thêm dấu cách ở cuối mỗi phần tử, dẫn đến thừa một dấu cách ở cuối mỗi dòng. Tuy nhiên, hầu hết các hệ thống chấm bài đều bỏ qua lỗi này, nhưng để in đúng chuẩn nên in như
printf("%d%c", a[i][j], j == n-1 ? '\n' : ' ');.
Bình luận