Các thuật toán trên dãy
Buổi 10
Python cho Tin học trẻ · Bảng B (THCS)
Buổi 10 – Các thuật toán trên dãy1 / 23
Hôm nay em sẽ học
- Tự viết thuật toán tìm lớn nhất / nhỏ nhất và vị trí
- Kỹ thuật biến cờ để kiểm tra "mọi phần tử đều …"
- Duyệt mọi cặp phần tử
- Tìm đoạn liên tiếp dài nhất
Buổi 10 – Các thuật toán trên dãy2 / 23
Khởi động: 10 tấm thẻ úp
Có 10 tấm thẻ úp, mỗi thẻ ghi một số. Em chỉ được nhớ một số trong đầu.
Làm sao tìm được thẻ có số lớn nhất?
Lật từng thẻ. Nếu số trên thẻ lớn hơn số đang nhớ → nhớ số mới. Đó chính là thuật toán tìm max!
Buổi 10 – Các thuật toán trên dãy3 / 23
Phần 1: Tìm lớn nhất
Số đang nhớ – và vị trí của nó
Buổi 10 – Các thuật toán trên dãy4 / 23
Tìm max và vị trí
n = int(input())
a = list(map(int, input().split()))
mx = a[0]
vt = 0
for i in range(1, n):
if a[i] > mx:
mx = a[i]
vt = i
print(mx, vt + 1)5
4 9 2 9 7
9 2
Không khởi tạo mx = 0 – sẽ sai khi dãy toàn số âm. Hãy khởi tạo bằng a[0].
Buổi 10 – Các thuật toán trên dãy5 / 23
Hàm có sẵn của Python
| Hàm | Ý nghĩa |
|---|
max(a), min(a) | giá trị lớn nhất, nhỏ nhất |
sum(a) | tổng |
a.count(x) | số lần x xuất hiện |
a.index(x) | vị trí đầu tiên của x (đếm từ 0) |
Khi đi thi được dùng. Nhưng em phải tự viết được để hiểu và để giải các bài biến thể.
Buổi 10 – Các thuật toán trên dãy6 / 23
Phần 2: Biến cờ
Giả sử đúng – tìm phản ví dụ
Buổi 10 – Các thuật toán trên dãy7 / 23
Dãy có tăng chặt không?
tang = True
for i in range(1, n):
if a[i] <= a[i - 1]:
tang = False
break
print("YES" if tang else "NO")- Giả sử dãy tăng:
tang = True - Duyệt tìm phản ví dụ: một chỗ không tăng
- Tìm thấy → hạ cờ
tang = False
Dùng cho mọi câu hỏi kiểu "tất cả các phần tử có … không?"
Buổi 10 – Các thuật toán trên dãy8 / 23
Phần 3: Duyệt mọi cặp
Hai vòng lặp lồng nhau
Buổi 10 – Các thuật toán trên dãy9 / 23
Đếm cặp có tổng bằng k
dem = 0
for i in range(n):
for j in range(i + 1, n):
if a[i] + a[j] == k:
dem += 1
print(dem)- j bắt đầu từ i + 1 để mỗi cặp chỉ đếm một lần
- Có khoảng n² ÷ 2 cặp
| n | Số cặp | Python |
|---|
| 1 000 | 500 000 | kịp |
| 100 000 | 5 tỷ | không kịp |
Buổi 10 – Các thuật toán trên dãy10 / 23
Phần 4: Đoạn liên tiếp
Leo cầu thang
Buổi 10 – Các thuật toán trên dãy11 / 23
Đoạn tăng liên tiếp dài nhất
Dãy: 1 2 5 3 4 6 8 2
| a[i] | 1 | 2 | 5 | 3 | 4 | 6 | 8 | 2 |
|---|
| hien_tai | 1 | 2 | 3 | 1 | 2 | 3 | 4 | 1 |
- Lớn hơn số trước → bậc thang tiếp tục:
hien_tai += 1 - Không lớn hơn → bắt đầu lại:
hien_tai = 1 - Kết quả là giá trị
hien_tai lớn nhất: 4
Buổi 10 – Các thuật toán trên dãy12 / 23
Viết thành code
best = 1
hien_tai = 1
for i in range(1, n):
if a[i] > a[i - 1]:
hien_tai += 1
else:
hien_tai = 1
best = max(best, hien_tai)
print(best)Chỉ duyệt dãy một lần → chạy rất nhanh, kể cả khi n = 10⁵.
Buổi 10 – Các thuật toán trên dãy13 / 23
Luyện tập
Dòng 1 là n (1 ≤ n ≤ 10⁵), dòng 2 là n số nguyên |aᵢ| ≤ 10⁹
Buổi 10 – Các thuật toán trên dãy14 / 23
Bài 1 ★ – MAXMIN
Output: giá trị lớn nhất và nhỏ nhất của dãy.
| Input | Output |
|---|
5
4 -9 2 9 7 | 9 -9 |
Tự viết vòng lặp, không dùng max, min.
Buổi 10 – Các thuật toán trên dãy15 / 23
Bài 2 ★ – VTMAX
Output: tất cả các vị trí (đánh số từ 1) đạt giá trị lớn nhất.
| Input | Output |
|---|
5
4 9 2 9 7 | 2 4 |
Buổi 10 – Các thuật toán trên dãy16 / 23
Bài 3 ★★ – KTTANG
Output: YES nếu dãy tăng chặt (mỗi số lớn hơn số đứng trước), ngược lại NO.
| Input | Output |
|---|
4
1 3 7 10 | YES |
3
1 3 3 | NO |
1
5 | YES |
Buổi 10 – Các thuật toán trên dãy17 / 23
Bài 4 ★★ – CAPTONG
Input: dòng 1 là n (n ≤ 1000) và k; dòng 2 là dãy n số.
Output: số cặp (i < j) có aᵢ + aⱼ = k.
| Input | Output |
|---|
5 6
1 5 3 3 2 | 2 |
Buổi 10 – Các thuật toán trên dãy18 / 23
Bài 5 ★★ – LONNHI
Output: giá trị lớn thứ hai (lớn nhất trong các số nhỏ hơn max), hoặc KHONG nếu không có.
| Input | Output |
|---|
5
4 9 2 9 7 | 7 |
3
5 5 5 | KHONG |
Buổi 10 – Các thuật toán trên dãy19 / 23
Bài 6 ★★★ – DOANTANG
Output: độ dài đoạn con liên tiếp tăng chặt dài nhất.
| Input | Output |
|---|
8
1 2 5 3 4 6 8 2 | 4 |
3
5 4 3 | 1 |
Buổi 10 – Các thuật toán trên dãy20 / 23
Bài 7 ★★★ – DOANTONG
Output: tổng lớn nhất của một đoạn con liên tiếp (có ít nhất một phần tử).
| Input | Output |
|---|
6
-2 3 -1 4 -6 2 | 6 |
3
-5 -2 -8 | -2 |
Gợi ý: giống bài 6 – nếu tổng đoạn đang xét bị âm thì bỏ đi, bắt đầu lại.
Buổi 10 – Các thuật toán trên dãy21 / 23
Tóm tắt buổi 10
| Kỹ thuật | Ý tưởng |
|---|
| Tìm max | nhớ số lớn nhất, gặp số lớn hơn thì thay |
| Biến cờ | giả sử đúng, tìm phản ví dụ |
| Duyệt cặp | for i … for j in range(i + 1, n) – chỉ khi n nhỏ |
| Đoạn liên tiếp | tiếp tục hoặc bắt đầu lại |
Buổi 10 – Các thuật toán trên dãy22 / 23
Bài về nhà
- Đếm số đỉnh của dãy: aᵢ lớn hơn cả hai phần tử kề bên (1 < i < n).
- Độ dài đoạn dài nhất gồm các phần tử bằng nhau liên tiếp.
- Dãy có phải cấp số cộng không? (hiệu hai số liên tiếp luôn bằng nhau)
Buổi 10 – Các thuật toán trên dãy23 / 23