Giải Tin Học 10 trang 116
Lời giải chi tiết SGK Lớp 10 · Môn Tin Há»c · Trang 116–119
Bài 23: Một số lệnh làm việc với dữ liệu danh sách
🔍 Kiến thức cần nhớ
1. Duyệt danh sách với toán tử in
Toán tử in có hai vai trò quan trọng khi làm việc với danh sách:
- Kiểm tra một phần tử có nằm trong danh sách hay không. Kết quả trả về
True(Đúng) hoặcFalse(Sai).
>>> A = [1, 2, 3, 4, 5]
>>> 2 in A
True
>>> 10 in A
False
- Duyệt nhanh từng phần tử của danh sách bằng vòng lặp
for, không cần dùngrange()và chỉ số.
>>> A = [10, 11, 12, 13, 14, 15]
>>> for k in A:
print(k, end=" ")
10 11 12 13 14 15
Khi thực hiện lệnh này, biến k lần lượt nhận các giá trị từ dãy A.
💡 Mẹo nhớ: Toán tửincó hai chức năng: -→ trả về True/False (kiểm tra thành viên). -in for→ duyệt từng phần tử (lặp).in
2. Một số lệnh (phương thức) làm việc với danh sách
| Lệnh | Chức năng |
|---|---|
A.append(x) | Bổ sung phần tử x vào cuối danh sách A |
A.insert(k, x) | Chèn phần tử x vào vị trí chỉ số k của danh sách A |
A.clear() | Xóa toàn bộ dữ liệu của danh sách A (A trở thành rỗng) |
A.remove(x) | Xóa phần tử đầu tiên có giá trị x trong A |
Một số lưu ý quan trọng:
A.remove(x)sẽ báo lỗi nếu giá trị x không có trong danh sách.- Với
A.insert(k, x): nếu k nằm ngoài phạm vi chỉ số thì lệnh vẫn có tác dụng: - Nếu k ≤ 0 → chèn vào đầu danh sách.
- Nếu k ≥ len(A) → chèn vào cuối danh sách.
>>> A = [1, 2, 6, 10]
>>> A.insert(2, 5)
>>> A
[1, 2, 5, 6, 10]
⚠️ Lưu ý thi: Phân biệt rõ: -append(x): chỉ có 1 tham số, luôn thêm vào cuối. -insert(k, x): có 2 tham số, chèn tại vị trí k. -remove(x): tham số là giá trị cần xóa, không phải chỉ số.
⚙️ Bài tập
Câu 1 (trang 117)
Đề bài: Giả sử A = [1, 2, 3, 4, 5]. Các biểu thức sau trả về giá trị đúng hay sai?
a) 1 in A
b) "01" in A
Cách 1 — Kiểm tra thành viên trực tiếp
a) 1 in A
Danh sách A = [1, 2, 3, 4, 5] có chứa số nguyên 1.
→ Biểu thức trả về True (Đúng).
b) "01" in A
"01" là một xâu kí tự (do đặt trong dấu nháy), khác hoàn toàn với số nguyên. Trong A chỉ có các số nguyên 1, 2, 3, 4, 5, không có phần tử nào là xâu "01".
→ Biểu thức trả về False (Sai).
⚠️ Lưu ý thi: Python phân biệt kiểu dữ liệu rất chặt.1(số nguyên) ≠"1"(xâu) ≠"01"(xâu). Đây là lỗi sai rất hay gặp khi kiểm tra thành viên.
Câu 2 (trang 117)
Đề bài: Hãy giải thích ý nghĩa từ khóa in trong câu lệnh sau:
for i in range(10):
print(i)
Cách 1 — Phân tích vai trò của in trong vòng lặp
Trong câu lệnh này, từ khóa in không có ý nghĩa kiểm tra thành viên (True/False). Thay vào đó, in là một phần của cú pháp vòng lặp for.
range(10)tạo ra dãy giá trị 0, 1, 2, ..., 9.- Từ khóa
incó nhiệm vụ chỉ ra rằng biếnisẽ lần lượt nhận từng giá trị trong dãy dorange(10)sinh ra. - Mỗi lần lặp,
inhận một giá trị và thực hiện lệnhprint(i).
Kết quả in ra: 0 1 2 3 4 5 6 7 8 9 (mỗi số một dòng).
💡 Mẹo nhớ:introngfor ... in ...mang nghĩa "duyệt qua từng phần tử", cònintrongx in Amang nghĩa "có thuộc về hay không".
Câu 3 (trang 118)
Đề bài: Khi nào thì lệnh A.append(1) và A.insert(0, 1) có tác dụng giống nhau?
Cách 1 — So sánh vị trí chèn
A.append(1): thêm số 1 vào cuối danh sách.A.insert(0, 1): chèn số 1 vào đầu danh sách (vị trí chỉ số 0).
Hai lệnh chèn vào hai đầu khác nhau, nên thông thường chúng cho kết quả khác nhau. Chúng chỉ giống nhau khi danh sách không có sự phân biệt giữa đầu và cuối, tức là khi:
Danh sách A đang rỗng (A = []).
Khi A rỗng, cả hai lệnh đều cho kết quả A = [1], vì lúc này đầu danh sách cũng chính là cuối danh sách.
Câu 4 (trang 118)
Đề bài: Danh sách A trước và sau lệnh là [1, 4, 10, 0] và [1, 4, 10, 5, 0]. Lệnh đã dùng là gì?
Cách 1 — Quan sát vị trí phần tử mới
So sánh hai danh sách:
- Trước:
[1, 4, 10, 0]→ chỉ số: A[0]=1, A[1]=4, A[2]=10, A[3]=0 - Sau:
[1, 4, 10, 5, 0]
Phần tử mới xuất hiện là số 5, nằm giữa 10 và 0, tức là tại vị trí chỉ số 3 (đẩy số 0 sang phải).
→ Lệnh đã dùng là:
A.insert(3, 5)
Cách 2 — Kiểm tra lại
Áp dụng A.insert(3, 5) vào [1, 4, 10, 0]: chèn 5 vào vị trí 3, đẩy 0 từ vị trí 3 sang vị trí 4.
→ Kết quả: [1, 4, 10, 5, 0]. ✓ Đúng.
⚙️ Thực hành
Nhiệm vụ 1
Đề bài: Nhập số n từ bàn phím, sau đó nhập danh sách n tên học sinh trong lớp và in ra danh sách học sinh này (mỗi tên trên một dòng). Yêu cầu danh sách được in ra theo thứ tự ngược lại với thứ tự đã nhập.
Cách 1 — Dùng insert(0, ...) để chèn vào đầu
Vì cần in ngược thứ tự nhập, ta dùng insert(0, ...) để mỗi tên mới được chèn vào đầu danh sách. Tên nhập sau cùng sẽ nằm ở đầu.
A = []
n = int(input("Nhập số học sinh: "))
for i in range(n):
ten = input("Nhập tên học sinh thứ " + str(i + 1) + ": ")
A.insert(0, ten)
print("Danh sách học sinh (thứ tự ngược):")
for ten in A:
print(ten)
Giải thích: mỗi lần insert(0, ten) đẩy tất cả tên cũ sang phải, đặt tên mới lên đầu. Kết quả là danh sách bị đảo ngược một cách tự nhiên.
Cách 2 — Nhập bình thường rồi đảo ngược
A = []
n = int(input("Nhập số học sinh: "))
for i in range(n):
A.append(input("Nhập tên: "))
for ten in A[::-1]: # duyệt từ cuối về đầu
print(ten)
Nhiệm vụ 2
Đề bài: Cho trước dãy số A. Viết chương trình xóa đi các phần tử có giá trị nhỏ hơn 0 từ A.
Cách 1 — Dùng vòng while và remove
Duyệt từng phần tử, nếu nhỏ hơn 0 thì xóa. Lưu ý: khi xóa, chỉ số không tăng vì các phần tử đã dịch sang trái.
A = [0, 1, -3, -10, 5, 9, -20, 55]
i = 0
while i < len(A):
if A[i] < 0:
A.remove(A[i]) # không tăng i vì phần tử mới dồn về vị trí i
else:
i = i + 1
print(A)
Kết quả: [0, 1, 5, 9, 55]
⚠️ Lưu ý thi: Khi xóa phần tử trong vòng lặp, không tăng chỉ số i ngay sau khi xóa. Nếu vẫn tăng i, ta sẽ bỏ sót phần tử dồn về vị trí vừa xóa. Đây là lỗi logic kinh điển.
Nhiệm vụ 3
Đề bài: Cho trước dãy số A. Viết chương trình tìm và chỉ ra vị trí đầu tiên của dãy A mà ba số hạng liên tiếp có giá trị là 1, 2, 3. Nếu tìm thấy thì thông báo vị trí, nếu không thì thông báo "Không tìm thấy mẫu".
Cách 1 — Duyệt và so khớp ba phần tử liên tiếp
A = [0, 4, 0, 1, 2, 3, 8, 9, 0, 1, 2, 3, 17, -16, 0, 1, 2]
B = [1, 2, 3]
k = -1 # k lưu vị trí tìm thấy, -1 nghĩa là chưa thấy
i = 0
while i < len(A) - 2 and k == -1:
if A[i] == B[0] and A[i + 1] == B[1] and A[i + 2] == B[2]:
k = i
else:
i = i + 1
if k >= 0:
print("Tìm thấy mẫu tại vị trí", k)
else:
print("Không tìm thấy mẫu")
Giải thích:
- Điều kiện lặp
i < len(A) - 2đảm bảo còn đủ 3 phần tử để so sánh (A[i], A[i+1], A[i+2]). - Điều kiện
k == -1giúp dừng vòng lặp ngay khi tìm thấy vị trí đầu tiên. - Với dãy A ở trên, mẫu 1, 2, 3 xuất hiện lần đầu tại vị trí chỉ số 3.
⚙️ Luyện tập (trang 119)
Câu 1
Đề bài: Cho dãy số [1, 2, 3, 4, 5]. Viết lệnh thực hiện:
a) Chèn số 4 vào ngay sau giá trị 3 của dãy.
b) Chèn số 2 và số 3 vào danh sách để dãy có số 2 và số 3 liền nhau hai lần.
Cách 1 — Dùng phương thức insert
a) Giá trị 3 nằm ở vị trí chỉ số 2. "Ngay sau 3" là vị trí chỉ số 3.
A = [1, 2, 3, 4, 5]
A.insert(3, 4)
print(A) # [1, 2, 3, 4, 4, 5]
b) Để dãy có cặp "2, 3" xuất hiện liền nhau hai lần, ta chèn thêm một cặp 2, 3 ngay sau cặp 2, 3 sẵn có (sau vị trí chỉ số 2).
A = [1, 2, 3, 4, 5]
A.insert(3, 3) # [1, 2, 3, 3, 4, 5]
A.insert(3, 2) # [1, 2, 3, 2, 3, 4, 5]
print(A) # [1, 2, 3, 2, 3, 4, 5]
Kết quả [1, 2, 3, 2, 3, 4, 5]: cặp "2, 3" xuất hiện ở vị trí 1–2 và vị trí 3–4, tức là liền nhau hai lần.
💡 Mẹo nhớ: Khi chèn nhiều phần tử vào cùng một vị trí, hãy chèn phần tử cuối cùng trước, vì mỗi lần chèn sẽ đẩy mọi thứ sang phải.
Câu 2
Đề bài: Cho trước dãy số A. Viết chương trình thực hiện:
- Xóa đi một phần tử ở chính giữa dãy nếu số phần tử của dãy là số lẻ.
- Xóa đi hai phần tử ở chính giữa của dãy nếu số phần tử của dãy là số chẵn.
Cách 1 — Xét tính chẵn lẻ của độ dài rồi xóa theo chỉ số
A = [10, 20, 30, 40, 50, 60, 70] # ví dụ dãy lẻ phần tử
n = len(A)
if n % 2 == 1:
# số phần tử lẻ: phần tử giữa ở vị trí n // 2
giua = n // 2
A.pop(giua) # hoặc: del A[giua]
else:
# số phần tử chẵn: hai phần tử giữa ở vị trí n//2 - 1 và n//2
giua = n // 2
A.pop(giua) # xóa phần tử bên phải trước
A.pop(giua - 1) # rồi xóa phần tử bên trái
print(A)
Giải thích vị trí giữa:
- Dãy lẻ n phần tử: phần tử giữa duy nhất ở chỉ số n // 2 (ví dụ n = 7 → chỉ số 3).
- Dãy chẵn n phần tử: hai phần tử giữa ở chỉ số n//2 − 1 và n//2 (ví dụ n = 8 → chỉ số 3 và 4).
⚠️ Lưu ý thi: Khi xóa hai phần tử bằng chỉ số, hãy xóa phần tử có chỉ số lớn hơn trước. Nếu xóa phần tử trái trước, các phần tử dồn sang trái và chỉ số phải sẽ lệch.
⚙️ Vận dụng (trang 119)
Câu 1
Đề bài: Viết chương trình nhập n từ bàn phím, tạo và in ra màn hình dãy số A bao gồm n số tự nhiên chẵn đầu tiên.
Cách 1 — Dùng vòng for và append
Các số tự nhiên chẵn đầu tiên là 0, 2, 4, 6, ... tức là 2×i với i = 0, 1, 2, ...
n = int(input("Nhập n: "))
A = []
for i in range(n):
A.append(2 * i)
print(A)
Ví dụ với n = 5 → A = [0, 2, 4, 6, 8].
Cách 2 — Dùng range với bước nhảy
range(0, 2*n, 2) sinh trực tiếp dãy số chẵn từ 0.
n = int(input("Nhập n: "))
A = list(range(0, 2 * n, 2))
print(A)
💡 Mẹo nhớ: Số chẵn thứ i (tính từ 0) luôn bằng 2×i. Đây là công thức gọn để sinh dãy số chẵn.
Câu 2
Đề bài: Dãy số Fibonacci được xác định như sau:
F0 = 0
F1 = 1
Fn = Fn−1 + Fn−2 với n ≥ 2
Viết chương trình nhập n từ bàn phím, tạo và in ra màn hình dãy số A bao gồm n số hạng đầu của dãy Fibonacci.
Cách 1 — Tính từng số hạng dựa vào hai số hạng trước
n = int(input("Nhập n: "))
A = []
for i in range(n):
if i == 0:
A.append(0)
elif i == 1:
A.append(1)
else:
A.append(A[i - 1] + A[i - 2])
print(A)
Ví dụ với n = 8 → A = [0, 1, 1, 2, 3, 5, 8, 13].
Cách 2 — Dùng hai biến phụ, không cần truy cập chỉ số
n = int(input("Nhập n: "))
A = []
a, b = 0, 1 # hai số hạng liên tiếp
for i in range(n):
A.append(a)
a, b = b, a + b # cập nhật đồng thời
print(A)
Cách này gọn và hiệu quả hơn vì chỉ lưu hai số hạng gần nhất thay vì truy cập lại danh sách.
⚠️ Lưu ý thi: Cần xử lý riêng hai số hạng đầu (F0 = 0, F1 = 1) trước khi áp dụng công thức truy hồi, nếu không chương trình sẽ báo lỗi truy cập chỉ số âm khi i = 0 hoặc i = 1.
🎯 Ghi nhớ: - Toán tửinvừa kiểm tra thành viên (x in A→ True/False), vừa dùng để duyệt (for x in A). - Bốn phương thức cốt lõi với danh sách:append(x)thêm cuối,insert(k, x)chèn tại vị trí k,remove(x)xóa theo giá trị,clear()xóa sạch. - Khi xóa phần tử trong vòng lặp: không tăng chỉ số sau khi xóa. - Khi chèn/xóa nhiều phần tử: thao tác với chỉ số lớn trước để tránh lệch vị trí.
