Hướng dẫn giải của Đổi thời gian


Chỉ dùng lời giải này khi không có ý tưởng, và đừng copy-paste code từ lời giải này. Hãy tôn trọng người ra đề và người viết lời giải.
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ập

Tác giả: Hiếu Nguyễn, Viet12, nquang2909, Khang2007

Hiểu bài toán

Bài toán yêu cầu chuyển đổi một số giây cho trước (n, 0 ≤ n < 86400) thành định dạng thời gian chuẩn hh:mm:ss. Trong đó hh là số giờ, mm là số phút, và ss là số giây còn lại. Đầu ra phải được định dạng sao cho mỗi thành phần (giờ, phút, giây) luôn hiển thị đúng 2 chữ số, ví dụ '05' thay vì '5'.

Các cách tiếp cận

Cách Phép chia lấy dư cơ bản
#include <stdio.h>

int main() {
    int n;
    scanf("%d", &n);

    int hh = n / 3600;
    n %= 3600; // Lấy phần dư sau khi trừ đi giờ
    int mm = n / 60;
    int ss = n % 60;

    // In ra với định dạng 2 chữ số
    printf("%02d:%02d:%02d", hh, mm, ss);

    return 0;
}
  • Time Complexity: O(1)
  • Space Complexity: O(1)

Đây là cách tiếp cận trực quan nhất. Chúng ta sử dụng các phép chia và lấy dư để lần lượt trích xuất số giờ, số phút và số giây.

  1. Số giờ (hh): Lấy thương của n khi chia cho 3600 (số giây trong 1 giờ).
  2. Cập nhật n: Lấy phần dư của n khi chia cho 3600 để loại bỏ phần đã tính là giờ.
  3. Số phút (mm): Lấy thương của n còn lại khi chia cho 60 (số giây trong 1 phút).
  4. Số giây (ss): Lấy phần dư của n khi chia cho 60. Phần in ra sử dụng định dạng %02d để tự động thêm số 0 ở phía trước nếu giá trị nhỏ hơn 10.
Cách Phép chia lấy dư kết hợp kiểm tra điều kiện
#include <stdio.h>

int main() {
    int n;
    scanf("%d", &n);

    int hh = n / 3600;
    n -= hh * 3600;
    int mm = n / 60;
    int ss = n - mm * 60;

    // Kiểm tra và in từng thành phần
    if (hh < 10) printf("0%d:", hh);
    else printf("%d:", hh);

    if (mm < 10) printf("0%d:", mm);
    else printf("%d:", mm);

    if (ss < 10) printf("0%d", ss);
    else printf("%d", ss);

    return 0;
}
  • Time Complexity: O(1)
  • Space Complexity: O(1)

Cách này thực hiện logic tính toán tương tự như cách 1 nhưng khác biệt ở phần xuất ra (output). Thay vì sử dụng các bộ định dạng (format specifier) như %02d của hàm printf, phương pháp này sử dụng các câu lệnh if-else.

  • Nếu giá trị của giờ/phút/giây nhỏ hơn 10, ta in ra ký tự '0' followed by giá trị đó.
  • Ngược lại, ta in ra giá trị đó bình thường. Phương pháp này giúp người mới học hiểu rõ cách kiểm soát đầu ra từng ký tự, nhưng code sẽ dài dòng và rườm rà hơn so với việc sử dụng định dạng chuỗi.
Cách In từng ký số
#include <stdio.h>

int main() {
    int n;
    scanf("%d", &n);

    int giay = n % 60;
    int phut = (n / 60) % 60;
    int gio = n / 3600;

    // Tách từng chữ số và in ra
    printf("%d%d:%d%d:%d%d", gio/10, gio%10, phut/10, phut%10, giay/10, giay%10);

    return 0;
}
  • Time Complexity: O(1)
  • Space Complexity: O(1)

Phương pháp này sử dụng các phép toán số học để trích xuất từng chữ số.

  1. Tính giá trị của giờ, phút, giây.
  2. Để in ra 2 chữ số, ta chia cho 10 để lấy chữ số hàng chục (nếu là số 1 chữ số, thương sẽ là 0) và lấy số dư modulo 10 để lấy chữ số hàng đơn vị. Ví dụ: ss = 5. ss/10 = 0, ss%10 = 5. In ra 05. Ví dụ: ss = 12. ss/10 = 1, ss%10 = 2. In ra 12. Cách này về cơ bản là tự tái hiện lại chức năng của %02d nhưng bằng phép toán.

Phân tích độ phức tạp

Cách tiếp cận Time Space Tên
1 O(1) O(1) Phép chia lấy dư cơ bản
2 O(1) O(1) Phép chia lấy dư kết hợp kiểm tra điều kiện
3 O(1) O(1) In từng ký số

Bài học kinh nghiệm

  • Số giây trong một ngày là 86400 (246060). Giả sử n < 86400 giúp ta không cần xử lý việc quá 24 giờ.
  • Cấu trúc Phép chia - Lấy dư - Phép chia - Lấy dư là công thức chuẩn để chuyển đổi đơn vị (giống đổi cơ số).
  • Sử dụng printf với định dạng "%02d" là cách hiệu quả nhất và ngắn gọn nhất trong C để đảm bảo đầu ra có đúng 2 chữ số.

Lỗi thường gặp

  • Quên cập nhật biến n sau khi tính giờ (ví dụ: n = n % 3600). Nếu không, khi tính phút, ta sẽ dùng sai giá trị tổng số giây ban đầu.
  • Xử lý sai định dạng đầu ra: In ra số lẻ một chữ số (ví dụ: '5' thay vì '05') sẽ khiến bài toán bị sai.
  • Sử dụng biến lưu trữ không cần thiết: Một số giải pháp khai báo quá nhiều biến hoặc thực hiện các phép tính cộng trừ rườm rà không cần thiết.

Bình luận

Please read the guidelines before commenting.


Không có bình luận tại thời điểm này.