Trần Nguyên Vũ • 20 ngày trước
Ta sẽ ví dụ với case mẫu ở hướng dẫn:
n = 9
2 4 5 2 2 4 5 4 3
Đầu tiên ta sẽ dùng mảng tần suất hoặc dùng hashmap hoặc ... để đếm số lượng giá trị a[i]
Giá trị a[i] | số lượng
2 | 3
3 | 1
4 | 3
5 | 2
Đơn giản với mảng tần suất:
#define MAX 10000
// Khởi tạo mảng tần suất
int b[MAX] = {0}; // Khởi tạo giá trị mặc định là 0
// Cách sử dụng:
// Dùng chính giá trị trong mảng a[i] để làm index
// Đảm bảo toàn bộ giá trị mảng là số nguyên dương và MAX >= giá trị max trong mảng
// Ví dụ sử dụng: b[a[i]]
Đầu tiên ta sẽ tạo 2 biến đếm riêng biệt để xử lý từng tình huống:
int dem_kq = 0; biến đếm kết quả (output)
int dem_2 = 0 biến đếm cho trường hợp hình CHỮ NHẬT.
Đầu tiên ta nhận ra rằng nếu a[i] có số lượng >= 4 thì chắc chắn sẽ tạo 1 hình vuông.
Ta sẽ tạo 1 vòng for để tìm tới các a[i] có sl >= 4 và đếm. Đảm bảo không trùng lặp giá trị trước đó khi duyệt. (Tránh lặp thì ta có thể tạo mảng tần suất để làm mảng true/false hoặc đơn giản hơn là dùng kiểu dữ liệu bool với index chính là a[i])
Thì input trên ko có giá trị nào thoả mãn thế nên biến dem_kq = 0
Tiếp theo ta sẽ dùng biến đếm dem_2 để đếm các a[i] có số lượng >= 2
Lúc này dem_2 = 3 với các giá trị thoả mãn là 2,4,5 đều có sl >= 2
Sau đó ta sẽ dùng công thức (dem_2*(dem_2 - 1))/2
Rồi cộng dồn vào biến dem_kq: dem_kq += (dem_2*(dem_2 - 1))/2
Cuối cùng output là 3 cho case này!
Tại sao ta dùng đến công thức này? (dem_2*(dem_2 - 1))/2
Các cặp thoả mãn để tạo hình chữ nhật là: (2,4) (2,5) (4,5) = 3
Lập ma trận 3x3:
--2 4 5
2 X T T
4 X X T
5 X X X
X là không thoả mãn
T là thoả mãn
Thì bn học qua đại số tuyến tính thì nhận ra rằng các cặp thoả mãn là nửa tam giác trên.
Đầu tiên là n nhân n sẽ tính được toàn bộ hình vuông này ở đây là 3x3
Mà dòng cuối cùng không thoả mãn do cả dòng đều là X hết thế nên ta sẽ phải trừ đi 1 dòng.
=> n*(n - 1)
Lúc này ma trận còn:
--2 4 5
2 X T T
4 X X T
Ta nhận ra ngay rằng toàn bộ số lượng cặp thoả mãn = không thoả mãn thì ta sẽ chia 2 đi.
Vậy ta sẽ hoàn thành công thức (n*(n-1))/2) để tính các cặp thoả mãn tạo nên hình chữ nhật với độ phức tạp o(1) cho việc tính toán và o(n) cho tìm a[i] có số lượng >= 2
Cuối cùng là cộng dồn dem_kq là xong bài toán :v Toàn bộ độ phức tạp là o(n)
Đọc đến đây chắc ae cũng mỏi mắt rồi nhỉ :v Mình viết lại để vững kiến thức. Ae nhớ tự cài đặt lại nhé :vv
Code mẫu cho ý tưởng trên:
#include <stdio.h>
#define MAX 10000
int main()
{
int n;
scanf("%d", &n);
int a[n];
int b[MAX] = {0}; // Mảng tần suất
int c[MAX] = {0}; // Mảng true/false với 0 là false, 1 là true
for(int i=0; i<n; i++)
{
scanf("%d", &a[i]);
b[a[i]]++; // Cập nhật số lượng của phần tử a[i]
}
int dem_kq = 0;
int dem_2 = 0;
for(int i=0; i<n; i++)
{
if(c[a[i]] == 0)
{
if(b[a[i]] >= 4)
dem_kq++;
if(b[a[i]] >= 2)
dem_2++;
c[a[i]] = 1; // Khoá lại giá trị này để tránh bị trùng lặp khi duyệt
}
}
printf("%d", dem_kq += (dem_2 * (dem_2-1))/2);
}
Bình luận: