Thuật toán & Giải thuật
Bộ sưu tập các bài toán lập trình经典 với lời giải chi tiết bằng C#, tuân thủ các nguyên tắc SOLID, CLEAN, DRY và có thể mở rộng.
Mục tiêu
- Code chất lượng: Clean code, SOLID principles, proper error handling
- Testability: Dễ dàng unit test, dependency injection
- Reusability: Code có thể reuse trong các ngữ cảnh khác
- Scalability: Giải pháp có thể mở rộng cho variants phức tạp hơn
- Performance: Phân tích time/space complexity
Danh sách bài toán
1. Bài toán cơ bản
| # | Tên bài | Độ khó | Khái niệm chính |
|---|---|---|---|
| 1 | Giải phương trình bậc nhất | Easy | Exception handling, validation, result pattern |
| 2 | Best Time to Buy/Sell Stock | Easy | Single pass, greedy algorithm |
Cấu trúc mỗi bài giải
Mỗi bài toán được trình bày theo cấu trúc:
- Đề bài: Mô tả yêu cầu, input/output
- Phân tích: Requirements, edge cases, constraints
- Giải pháp: Code với giải thích chi tiết
- Unit Tests: Test cases đầy đủ
- Mở rộng: Variants phức tạp hơn của bài toán
- Giải pháp mở rộng: Code cho variants
Nguyên tắc coding áp dụng
SOLID Principles
S - Single Responsibility: Mỗi class/method một trách nhiệm
O - Open/Closed: Mở cho extension, đóng cho modification
L - Liskov Substitution: Derived classes thay thế được base classes
I - Interface Segregation: Interfaces nhỏ, specific
D - Dependency Inversion: Depend vào abstractions
CLEAN Code
- Đặt tên có ý nghĩa (meaningful names)
- Functions nhỏ, làm một việc
- Comments tối thiểu, code tự giải thích
- Error handling rõ ràng
- No magic numbers
DRY (Don’t Repeat Yourself)
- Extract common logic
- Use helper methods
- Generic solutions when applicable
Các khái niệm thường dùng
Result Pattern
Thay vì ném exception, trả về result object:
public class Result<T>
{
public bool IsSuccess { get; }
public T Value { get; }
public string Error { get; }
private Result(bool isSuccess, T value, string error)
{
IsSuccess = isSuccess;
Value = value;
Error = error;
}
public static Result<T> Success(T value)
=> new Result<T>(true, value, null);
public static Result<T> Failure(string error)
=> new Result<T>(false, default, error);
}
Guard Clauses
public static class Guard
{
public static void AgainstNull<T>(T value, string paramName)
where T : class
{
if (value == null)
throw new ArgumentNullException(paramName);
}
public static void AgainstNullOrEmpty(string value, string paramName)
{
if (string.IsNullOrEmpty(value))
throw new ArgumentException("Value cannot be empty", paramName);
}
public static void AgainstNullOrEmpty<T>(IEnumerable<T> value, string paramName)
{
if (value == null || !value.Any())
throw new ArgumentException("Collection cannot be empty", paramName);
}
}