Hướng dẫn giải của Chuyển chuỗi về viết thường
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.
Lời giải này đang bị ẩn cho đến khi bạn chọn mở ra.
Chúng tôi khuyên bạn nên tự thử giải bài trước. Việc mở lời giải có thể làm lộ mất ý tưởng chính trước khi bạn có cơ hội tự giải.
Bạn phải đăng nhập để mở lời giải này.
Đăng nhậpTác giả: , , ,
Hiểu bài toán
Bài toán yêu cầu chuyển đổi một chuỗi ký tự bao gồm các ký tự tiếng Anh in hoa (A-Z), in thường (a-z) và khoảng trắng thành dạng viết thường. Các ký tự in hoa cần được chuyển thành in thường, trong khi các ký tự in thường và khoảng trắng được giữ nguyên. Độ dài chuỗi đầu vào không quá 1000 ký tự.
Các cách tiếp cận
Cách Dùng hàm thư viện (tolower)
#include<stdio.h>
#include<string.h>
#include<ctype.h>
int main(){
char a[100];
fgets(a,100,stdin);
for(int i =0;i<strlen(a);i++){
if(isupper(a[i])){
a[i]=tolower(a[i]);
}
}
printf("%s",a);
return 0;
}
- Time Complexity: O(n)
- Space Complexity: O(1)
Cách tiếp cận này sử dụng các hàm tiện ích có sẵn trong thư viện <ctype.h> như isupper() để kiểm tra một ký tự có phải là in hoa hay không, và tolower() để chuyển đổi nó sang in thường. Vòng lặp duyệt qua từng ký tự của chuỗi, kiểm tra và chuyển đổi nếu cần. Đây là cách viết ngắn gọn, dễ đọc và dễ hiểu nhất.
Cách Tính toán số học (Math)
#include <stdio.h>
#include <string.h>
int main()
{
char c[1000];
gets(c);
for(int i=0;i<strlen(c);i++)
{
int tam=(int)c[i];
if(tam>=65 && tam<=90) // Kiểm tra mã ASCII của 'A' đến 'Z'
{
tam+=32; // Khoảng cách giữa 'A' và 'a' là 32
c[i]=(char)tam;
}
}
printf("%s",c);
return 0;
}
- Time Complexity: O(n)
- Space Complexity: O(1)
Phương pháp này dựa trên bảng mã ASCII. Ký tự 'A' có mã 65 và 'a' có mã 97. Do đó, khoảng cách giữa một ký tự in hoa và ký tự in thường tương ứng của nó là 32. Bằng cách kiểm tra xem mã ASCII của ký tự có nằm trong khoảng từ 65 đến 90 không, ta có thể cộng thêm 32 vào mã ASCII đó để chuyển đổi sang ký tự in thường. Cách này không cần thư viện phụ và chạy nhanh, nhưng phụ thuộc vào bảng mã ASCII (mặc dù hầu hết các hệ thống đều sử dụng ASCII).
Cách Thao tác trực tiếp với mã ASCII
#include<stdio.h>
#include<ctype.h>
#include<math.h>
#include<string.h>
#include<stdlib.h>
char s[101010];
void solve(ll iTest){
fgets(s, sizeof s, stdin);
s[strcspn(s, "\n")] = '\0';
int nsize = strlen(s);
for(int i = 0; i < nsize; i++){
if(s[i] >= 'A' && s[i] <= 'Z'){
s[i] = (char) ((int) s[i] - (int) 'A' + (int) 'a');
}
}
printf("%s", s);
}
int main(){
solve(1);
return 0;
}
- Time Complexity: O(n)
- Space Complexity: O(1)
Đây là biến thể của phương pháp số học nhưng được viết một cách an toàn hơn bằng cách sử dụng các ký tự 'A' và 'a' làm tham chiếu thay vì các hằng số số nguyên 65 và 97. Biểu thức s[i] = (char) ((int) s[i] - (int) 'A' + (int) 'a' thực chất là s[i] = s[i] - 'A' + 'a'. Nó trừ đi giá trị cơ sở của ký tự in hoa và cộng thêm giá trị cơ sở của ký tự in thường. Cách này đảm bảo hoạt động đúng ngay cả trên các hệ thống mã hóa khác mà không phải là ASCII.
Phân tích độ phức tạp
| Cách tiếp cận | Time | Space | Tên |
|---|---|---|---|
| 1 | O(n) | O(1) | Dùng hàm thư viện (tolower) |
| 2 | O(n) | O(1) | Tính toán số học (Math) |
| 3 | O(n) | O(1) | Thao tác trực tiếp với mã ASCII |
Bài học kinh nghiệm
- Chuyển đổi từ in hoa sang in thường chỉ là một phép toán số học đơn giản dựa trên bảng mã ASCII.
- Sử dụng các hàm thư viện (
tolower,isupper) giúp code ngắn gọn, dễ đọc và giảm thiểu lỗi. - Vì độ dài chuỗi nhỏ (<= 1000), độ phức tạp O(n) là hoàn toàn thỏa mãn.
Lỗi thường gặp
- Sử dụng hàm
gets()có thể gây tràn bộ đệm (buffer overflow) nếu input dài hơn kích thước mảng khai báo. Nên dùngfgets()để an toàn hơn. - Quên loại ký tự newline (
\n) khi nhập chuỗi bằngfgets()có thể dẫn đến việc in ra thêm một dòng trống hoặc xử lý sai ký tự cuối. - Nếu sử dụng toán tử số học, cần đảm bảo biến được ép kiểu đúng để không bị lỗi tràn số (ví dụ:
charcó thể là signed hoặc unsigned).
Bình luận