Trong bài này
Lan có sáu lượt mượn sách và muốn tìm ba tên được nhắc đến nhiều nhất. Một chương trình cần đọc tên, đếm lượt, sắp xếp và in kết quả. Mỗi bước dùng một công cụ bạn đã học.
Các chặng của khóa học kết nối với nhau
Nhập xuất và biếnNhận dữ liệu, lưu giá trị và in kết quảĐiều kiện và vòng lặpChọn nhánh và lặp các bướcHàmTách việc và trả kết quảDữ liệuChọn chuỗi, list, bảng, tuple, set hoặc dictLỗi và máy chấmTự kiểm tra và in đúng định dạng
Một phép tính có đầu vào và kết quả cụ thể. Hai số dưới đây là số sách của hai lớp:
12 15
a, b = map(int, input().split())
tong = a + b
print(tong)27
input() nhận dòng, map đổi hai phần thành số, còn print gửi tổng. Khi đề có nhiều dòng, bạn cần đọc đúng số dòng được mô tả.
Điều kiện chọn việc cần làm; vòng lặp xét lần lượt các giá trị. Trong ví dụ, chỉ các số lớn hơn hoặc bằng 5 được cộng:
diem = [4, 7, 5]
tong = 0
for x in diem:
if x >= 5:
tong += x
print(tong)12
Chọn cấu trúc dữ liệu theo câu hỏi
| Câu hỏi | Cấu trúc phù hợp | Bài đã học |
|---|---|---|
| Cần giữ thứ tự các điểm và sửa từng điểm? | list | 10 |
| Cần loại tên trùng? | set | 13 |
| Cần tra số lượt theo tên? | dict | 13 |
| Cần lưu lưới theo hàng và cột? | list hai chiều | 12 |
| Cần lưu một tọa độ gồm hàng và cột? | tuple | 13 |
| Cần xử lý từng ký tự của câu? | Chuỗi | 9 |
Cùng một tập tên có thể cần cả set lẫn dict: set giữ tên khác nhau, còn dict lưu thêm số lần mỗi tên xuất hiện.
ten = ["An", "Binh", "An"]
dem = {}
for x in ten:
dem[x] = dem.get(x, 0) + 1
print(len(set(ten)))
print(dem["An"])2 2
Kết quả cho biết có hai tên khác nhau và An xuất hiện hai lần. Nếu cần thứ tự in xác định, hãy sắp xếp thay vì dựa vào thứ tự duyệt set.
Giải bài thống kê lượt mượn qua nhiều bước
Đề cho n tên, mỗi tên một dòng và không có dấu cách. In tối đa ba tên cùng số lượt, theo số lượt giảm dần; nếu bằng nhau, tên tăng dần. Ví dụ có sáu lượt: An, Binh, An, Chi, Binh, An. Kết quả theo thứ tự là An 3, Binh 2, Chi 1.
Đầu tiên, đọc số dòng và lưu tên. Mỗi khối sau đây chạy độc lập:
3 An Binh An
n = int(input())
ten = []
for _ in range(n):
ten.append(input())
print(ten)['An', 'Binh', 'An']
Danh sách có ba phần tử, kể cả tên lặp. Tiếp theo, dùng get để bắt đầu từ 0 khi chưa có khóa:
ten = ["An", "Binh", "An"]
dem = {}
for x in ten:
dem[x] = dem.get(x, 0) + 1
print(dem){'An': 2, 'Binh': 1}
Mỗi cặp trong dem.items() có dạng (tên, số lượt). Khóa sắp xếp (-số lượt, tên) đưa lượt lớn lên trước, rồi giải hòa theo tên:
dem = {"An": 2, "Binh": 2, "Chi": 1}
hang = sorted(dem.items(), key=lambda cap: (-cap[1], cap[0]))
for ten, luot in hang[:3]:
print(ten, luot)An 2 Binh 2 Chi 1
An đứng trước Binh vì cùng hai lượt và tên An nhỏ hơn theo thứ tự chuỗi. Lát cắt [:3] vẫn dùng được khi có ít hơn ba tên.
Bản hoàn chỉnh tách việc đọc, xử lý và in. Dữ liệu đi từ hàm này sang hàm khác qua giá trị trả về:
6 An Binh An Chi Binh An
def doc():
n = int(input())
return [input() for _ in range(n)]
def xu_ly(ds):
dem = {}
for ten in ds:
dem[ten] = dem.get(ten, 0) + 1
return sorted(dem.items(), key=lambda cap: (-cap[1], cap[0]))[:3]
def in_ket_qua(hang):
for ten, luot in hang:
print(ten, luot)
in_ket_qua(xu_ly(doc()))An 3 Binh 2 Chi 1
Mỗi dòng kết quả chỉ có tên, một dấu cách và số lượt. Với n = 0, danh sách rỗng và chương trình không in dòng nào.
Các cặp thao tác dễ nhầm
print hiển thị; return gửi giá trị về nơi gọi hàm:
def gap_doi(x):
return x * 2
kq = gap_doi(4)
print(kq + 1)9
Nếu chỉ in trong hàm mà không trả về, biến nhận kết quả là None, không phải 8.
= gán giá trị, còn == so sánh hai giá trị:
diem = 7
print(diem == 7)
print(diem == 8)True False
Hai phép so sánh cho kết quả Boolean; chúng không thay đổi diem.
b = a dùng chung list; a[:] tạo list mới:
a = [2, 4]
b = a
c = a[:]
b[0] = 9
print(a, c)[9, 4] [2, 4]
Thay phần tử qua b cũng đổi a, nhưng không đổi c trong ví dụ một chiều này.
sort sửa list tại chỗ; sorted tạo list mới:
a = [3, 1, 2]
b = sorted(a)
print(a, b)
a.sort()
print(a)[3, 1, 2] [1, 2, 3] [1, 2, 3]
Không dùng kết quả trả về của a.sort() như list đã sắp: phương thức này trả None.
/ chia thông thường; // chia làm tròn xuống:
print(7 / 2)
print(7 // 2)
print(-7 // 2)3.5 3 -4
Với số âm, làm tròn xuống cho -4, không phải -3.
remove xóa theo giá trị; pop xóa theo chỉ số và trả phần tử:
a = [4, 7, 4]
a.remove(4)
x = a.pop(1)
print(a, x)[7] 4
remove(4) xóa lần xuất hiện đầu; sau đó pop(1) lấy phần tử ở chỉ số 1.
d[k] cần khóa tồn tại; d.get(k, 0) cho 0 nếu thiếu:
dem = {"An": 2}
print(dem.get("Binh", 0))
print(dem["An"])0 2
Truy cập dem["Binh"] trong ví dụ này gây KeyError; get phù hợp khi cần giá trị mặc định.
Nhân một hàng tạo các tham chiếu chung; comprehension tạo các hàng riêng:
x = [[0] * 2] * 2
y = [[0] * 2 for _ in range(2)]
x[0][0] = 1
y[0][0] = 1
print(x)
print(y)[[1, 0], [1, 0]] [[1, 0], [0, 0]]
Ở x, cả hai hàng đổi vì dùng chung list hàng. Ở y, chỉ hàng đầu đổi.
Quy trình nộp bài giúp phát hiện lỗi
- Đọc đề, định dạng vào ra và giới hạn.
- Tự tính một ví dụ nhỏ trước khi viết code.
- Tách bước đọc, xử lý, in; viết và thử từng bước.
- Thử ca biên như dữ liệu nhỏ nhất, trùng nhau và rỗng nếu đề cho phép.
- Bỏ các dòng in dò lỗi và kiểm tra khoảng trắng, số dòng.
- Nộp và đọc phản hồi; nếu sai, tìm một ca làm chương trình sai.
Tự kiểm tra trước khóa Nâng Cao
- Đọc
nsố bằngsys.stdin, theo đúng cách đề cho dữ liệu. - Viết hàm có
returnvà dùng kết quả ở bước tiếp theo. - Đếm tần suất bằng
dictvà sắp xếp theo nhiều tiêu chí. - Duyệt lưới, kiểm tra biên trước khi xét ô kề.
- Ước lượng hai vòng lồng nhau: mỗi vòng
nlượt tạo khoảngn * nlượt trong thân.
Nếu còn vướng một việc, hãy quay lại bài tương ứng trong bảng và tự thử dữ liệu khác. Bài 1 Nâng Cao bắt đầu bằng việc đọc dữ liệu và in đúng định dạng cho máy chấm. Bài 2 phân tích chi phí của chương trình khi dữ liệu lớn.
Lỗi thường gặp
| Lỗi | Vì sao sai | Cách sửa |
|---|---|---|
Chỉ print trong hàm cần trả kết quả | Nơi gọi nhận None | Dùng return |
Dùng = để so sánh | Đây là phép gán | Dùng == |
Dùng b = a để sao chép list | Hai tên cùng chỉ list | Dùng a[:] cho list một chiều |
Gán kết quả a.sort() vào list | sort trả None | Gọi riêng a.sort() hoặc dùng sorted(a) |
Truy cập khóa chưa có bằng d[k] | Gây KeyError | Dùng get với mặc định phù hợp |
Tạo bảng bằng [[0] * m] * n | Các hàng cùng một list | Dùng comprehension tạo từng hàng |
Tóm tắt
Chọn cấu trúc theo thao tác cần làm, rồi chia bài thành đọc, xử lý và in. Kiểm tra thứ tự, dữ liệu biên và định dạng trước khi nộp. Các hàm và cấu trúc dữ liệu phối hợp với nhau trong một lời giải.