Đối xứng
Đề bài
Bạn được cho một số nguyên dương $N$. Hãy kiểm tra số $N$ đó có phải là một số đối xứng hay không. Một số được gọi là đối xứng nếu như ta gọi $M$ là số được viết từ số $N$ nhưng viết các chữ số theo thứ tự ngược lại, thì ta được $N = M$.
Ví dụ $N = 12321$ được gọi là một số đối xứng, vì nếu ta lấy số $M$ là số được tạo thành bởi việc viết các chữ số trong số $N$ nhưng theo thứ tự ngược lại, ta vẫn được $M = 12321$.
Số $N = 102$ không được gọi là số đối xứng, vì $M = 201$ khác với $102$.
Dữ liệu nhập: gồm một số nguyên dương duy nhất là số $N$ $(1 \le N \le 1000000)$.
Dữ liệu xuất: gồm một chuỗi duy nhất là YES hay NO. Chuỗi là YES nếu như $N$ là số đối xứng và NO trong trường hợp ngược lại.
12321YES102NOLời mở đầu
Kiểm tra số đối xứng thì các bạn đã làm bằng vòng lặp từ hồi học vòng while. Trong chương Đệ quy cơ bản, mình làm lại bài này theo 2 kiểu đệ quy rất hay gặp: đệ quy có tham số "tích luỹ" (lật số) và đệ quy co hai đầu trên xâu.
Link này chỉ học viên đã tham gia tổ chức mới vào được. Học viên nên ưu tiên nộp ở đây vì sẽ được chấm nhanh hơn.
Nộp bài trên CLUE OJLộ trình lời giải, bấm vào từng phần để nhảy tới:
Bộ testBộ test chính thức có gì?
| Số chữ số của N | 2 | 3 | 4 | 5 | 6 | Tổng |
|---|---|---|---|---|---|---|
| Số test | 16 | 28 | 13 | 33 | 10 | 100 |
| Trong đó YES | 8 | 19 | 2 | 22 | 0 | 51 |
- 100 test, $N$ từ 11 đến 987.550 (không có số 1 chữ số; không có test $N = 10^6$). Có 51 test đáp án
YESvà 49 testNO; các test 53–100 đều là số đối xứng. - Không chia subtask: $N$ có tối đa 7 chữ số nên mọi cách làm đều chỉ tốn vài phép tính – độ sâu đệ quy không quá 8 tầng.
- Số lật của $N$ không vượt quá $9.999.999$, vẫn nằm gọn trong
int.
Ý tưởngHai cách nghĩ đệ quy
dao(n, m): $n$ là phần chưa lật, $m$ là phần đã lật. Mỗi lần gọi, chuyển chữ số cuối của $n$ (là n % 10) sang cuối $m$: dao(n / 10, m * 10 + n % 10). Khi $n = 0$ thì $m$ chính là số lật. Ví dụ: dao(102, 0) → dao(10, 2) → dao(1, 20) → dao(0, 201) = 201 ≠ 102 → NO.s[l..r] đối xứng khi và chỉ khi s[l] == s[r] và đoạn bên trong s[l+1..r-1] đối xứng. Điểm dừng: đoạn còn 0 hoặc 1 ký tự ($l \ge r$) thì chắc chắn đối xứng.Em chọn cách, nhập $N$ rồi bấm Tiếp để xem cây đệ quy:
Cách 1Đệ quy lật số
- Đây là đệ quy đuôi: lời gọi đệ quy là việc cuối cùng của hàm, kết quả ở điểm dừng được "chuyền" nguyên vẹn về
main. - Tham số
mđóng vai trò biến tích luỹ – giống biếnm = m * 10 + n % 10trong vòngwhilequen thuộc, chỉ khác là mỗi vòng lặp giờ là một lời gọi hàm. - Lời gọi đầu tiên phải là
dao(n, 0)– lúc đầu chưa lật được chữ số nào.
Kết quả chạy thật: bản C++ đúng 100/100 test, test đúng chạy lâu nhất 0.005s; bản Python đúng 100/100 test, test đúng chạy lâu nhất 0.035s.
Cách 2Đệ quy co hai đầu xâu
- Đọc $N$ thẳng vào
string s(vì $N$ không có số 0 ở đầu nên xâu chính là cách viết của số). - Gặp một cặp khác nhau là
return falsengay, không cần xét phần bên trong. Ví dụ102:s[0] = '1'≠s[2] = '2'→NOchỉ sau 1 lời gọi. - Mỗi lời gọi co mỗi đầu vào 1 ký tự, nên số lời gọi khoảng (số chữ số) / 2.
Kết quả chạy thật: bản C++ đúng 100/100 test, test đúng chạy lâu nhất 0.003s; bản Python đúng 100/100 test, test đúng chạy lâu nhất 0.026s.
Tổng kếtKết quả chạy thật trên bộ test
| Cách | Ngôn ngữ | Đúng | Lâu nhất | Ghi chú |
|---|---|---|---|---|
| 1. Lật số | C++ | 100/100 | 0.005s | Full điểm |
| Python | 100/100 | 0.035s | Full điểm | |
| 2. Co hai đầu xâu | C++ | 100/100 | 0.003s | Full điểm |
| Python | 100/100 | 0.026s | Full điểm |
f(l, r) → f(l + 1, r - 1) của Cách 2 sẽ còn gặp lại nhiều ở các bài đảo ngược mảng, kiểm tra xâu đối xứng bằng đệ quy ở những bài sau.
Nhận xét
Đăng nhận xét