Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,8 @@ debug_*

# Temporary files
*.tmp
temp/
temp/

# Local test binaries
test_each_approach
test_transpose
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ edition = "2021"
authors = ["Marvin Tutt <marvin@caiatech.com>"]
description = "Comprehensive LeetCode solutions in Rust with multiple approaches, benchmarking, and property-based testing"
license = "MIT"
repository = "https://github.com/yourusername/rust-leetcode"
repository = "https://github.com/caia-tech/rust-leetcode"
readme = "README.md"
homepage = "https://github.com/yourusername/rust-leetcode"
homepage = "https://github.com/caia-tech/rust-leetcode"
documentation = "https://docs.rs/rust-leetcode"
keywords = ["leetcode", "algorithms", "data-structures", "rust"]
categories = ["algorithms", "data-structures"]
Expand Down
54 changes: 52 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,61 @@
# Rust LeetCode Solutions

A comprehensive collection of LeetCode solutions in Rust, featuring multiple algorithmic approaches, extensive testing, and performance benchmarking.
A curated collection of [LeetCode](https://leetcode.com/) solutions implemented in Rust.
Problems are organized by difficulty and each module exposes a `Solution` type with multiple algorithmic approaches and tests.

## Repository Layout

```
src/ # Problem implementations grouped by difficulty
├── easy/
├── medium/
└── hard/
src/utils/ # Shared data structures and helpers
examples/ # Small executable usage examples
tests/ # Integration and property tests
benches/ # Criterion benchmarks
```

See [PROJECT_STATUS.md](PROJECT_STATUS.md) for progress and
[README_BENCHMARKS.md](README_BENCHMARKS.md) for benchmarking notes.

## Usage

Add the crate to your project and call solution methods:

```rust
use rust_leetcode::easy::two_sum::Solution;

fn main() {
let solution = Solution::new();
let result = solution.two_sum(vec![2, 7, 11, 15], 9);
assert_eq!(result, vec![0, 1]);
}
```

## Development

Run tests with:

```bash
cargo test
```

Run benchmarks (see [README_BENCHMARKS.md](README_BENCHMARKS.md)):

```bash
cargo bench
```

## Contributing

Contributions are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.

## License

MIT

## Author

Marvin Tutt, Caia Tech
Built with Rust 🦀 for learning and interview preparation + AI training

111 changes: 111 additions & 0 deletions src/easy/add_digits.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
//! # Problem 258: Add Digits
//!
//! Given an integer `num`, repeatedly add all its digits until the result has only one digit, and return it.
//!
//! ## Examples
//!
//! ```
//! use rust_leetcode::easy::add_digits::Solution;
//!
//! let solution = Solution::new();
//!
//! assert_eq!(solution.add_digits_iterative(38), 2); // 3 + 8 = 11, 1 + 1 = 2
//! assert_eq!(solution.add_digits_math(38), 2);
//! ```
//!
//! ## Constraints
//!
//! - `0 <= num <= i32::MAX`
//!
/// Solution struct following LeetCode conventions
pub struct Solution;

impl Solution {
/// Create a new instance of `Solution`
pub fn new() -> Self {
Solution
}

/// # Approach 1: Iterative Digit Summation
///
/// Repeatedly sums the digits of `num` until a single digit remains.
///
/// **Algorithm**
/// 1. While `num` has more than one digit, compute the sum of its digits.
/// 2. Replace `num` with this sum and repeat.
///
/// **Time Complexity:** `O(k)` per iteration where `k` is number of digits. In worst case, `O(log n)` overall.
/// **Space Complexity:** `O(1)`
pub fn add_digits_iterative(&self, mut num: i32) -> i32 {
while num >= 10 {
let mut sum = 0;
let mut n = num;
while n > 0 {
sum += n % 10;
n /= 10;
}
num = sum;
}
num
}

/// # Approach 2: Digital Root Formula
///
/// Uses mathematical property of digital roots: the result is `1 + (num - 1) % 9`
/// for positive `num`, and `0` when `num` is `0`.
///
/// **Time Complexity:** `O(1)`
/// **Space Complexity:** `O(1)`
pub fn add_digits_math(&self, num: i32) -> i32 {
if num == 0 {
0
} else {
1 + (num - 1) % 9
}
}
}

#[cfg(test)]
mod tests {
use super::*;
use rstest::rstest;

fn setup() -> Solution {
Solution::new()
}

#[rstest]
#[case(0, 0)]
#[case(5, 5)]
#[case(9, 9)]
#[case(10, 1)]
#[case(38, 2)]
#[case(12345, 6)] // 1+2+3+4+5 = 15 -> 1+5 = 6
#[case(99999, 9)]
fn test_add_digits_iterative(#[case] input: i32, #[case] expected: i32) {
let solution = setup();
assert_eq!(solution.add_digits_iterative(input), expected);
}

#[rstest]
#[case(0, 0)]
#[case(1, 1)]
#[case(38, 2)]
#[case(12345, 6)]
#[case(99999, 9)]
fn test_add_digits_math(#[case] input: i32, #[case] expected: i32) {
let solution = setup();
assert_eq!(solution.add_digits_math(input), expected);
}

#[test]
fn test_consistency_between_methods() {
let solution = setup();
for num in [0, 1, 2, 9, 10, 11, 38, 99, 12345, i32::MAX] {
assert_eq!(
solution.add_digits_iterative(num),
solution.add_digits_math(num)
);
}
}
}
6 changes: 3 additions & 3 deletions src/easy/best_time_to_buy_and_sell_stock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@
//!
//! ## Examples
//!
//! ```
//! ```text
//! Input: prices = [7,1,5,3,6,4]
//! Output: 5
//! Explanation: Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5.
//! Note that buying on day 2 and selling on day 1 is not allowed because you must buy before you sell.
//! ```
//!
//! ```
//! ```text
//! Input: prices = [7,6,4,3,2,1]
//! Output: 0
//! Explanation: In this case, no transactions are done and the max profit = 0.
Expand Down Expand Up @@ -56,7 +56,7 @@ impl Solution {
/// - Natural logic that follows the problem constraints
///
/// **Visualization:**
/// ```
/// ```text
/// prices = [7,1,5,3,6,4]
/// min_price: 7→1→1→1→1→1
/// profit: 0→0→4→4→5→5
Expand Down
108 changes: 108 additions & 0 deletions src/easy/contains_duplicate.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
//! # Problem 217: Contains Duplicate
//!
//! Given an integer array `nums`, return `true` if any value appears at least twice
//! in the array, and return `false` if every element is distinct.
//!
//! ## Examples
//!
//! ```
//! use rust_leetcode::easy::contains_duplicate::Solution;
//!
//! let solution = Solution::new();
//!
//! assert!(solution.contains_duplicate_set(vec![1, 2, 3, 1]));
//! assert!(!solution.contains_duplicate_sort(vec![1, 2, 3, 4]));
//! ```
//!
//! ## Constraints
//!
//! - `1 <= nums.len() <= 10^5`
//! - `-10^9 <= nums[i] <= 10^9`
//!
/// Solution struct following LeetCode conventions
pub struct Solution;

impl Solution {
/// Create a new instance of `Solution`
pub fn new() -> Self {
Solution
}

/// # Approach 1: Hash Set Tracking
///
/// Inserts elements into a `HashSet` and checks for duplicates as we iterate.
///
/// **Time Complexity:** `O(n)` on average, where `n` is the length of `nums`.
/// **Space Complexity:** `O(n)` for the set.
pub fn contains_duplicate_set(&self, nums: Vec<i32>) -> bool {
use std::collections::HashSet;
let mut seen = HashSet::with_capacity(nums.len());
for &num in &nums {
if !seen.insert(num) {
return true;
}
}
false
}

/// # Approach 2: Sorting
///
/// Sorts the array and then checks adjacent elements for equality.
///
/// **Time Complexity:** `O(n \log n)` due to sorting.
/// **Space Complexity:** `O(1)` or `O(n)` depending on sort implementation.
pub fn contains_duplicate_sort(&self, mut nums: Vec<i32>) -> bool {
nums.sort_unstable();
nums.windows(2).any(|w| w[0] == w[1])
}
}

#[cfg(test)]
mod tests {
use super::*;
use rstest::rstest;

fn setup() -> Solution {
Solution::new()
}

#[rstest]
#[case(vec![1, 2, 3, 1], true)]
#[case(vec![1, 2, 3, 4], false)]
#[case(vec![1, 1, 1, 3, 3, 4, 3, 2, 4, 2], true)]
#[case(vec![0; 1], false)]
#[case(vec![0, 0], true)]
fn test_contains_duplicate_set(#[case] nums: Vec<i32>, #[case] expected: bool) {
let solution = setup();
assert_eq!(solution.contains_duplicate_set(nums), expected);
}

#[rstest]
#[case(vec![1, 2, 3, 1], true)]
#[case(vec![1, 2, 3, 4], false)]
#[case(vec![1, 1, 1, 3, 3, 4, 3, 2, 4, 2], true)]
#[case(vec![0; 1], false)]
#[case(vec![0, 0], true)]
fn test_contains_duplicate_sort(#[case] nums: Vec<i32>, #[case] expected: bool) {
let solution = setup();
assert_eq!(solution.contains_duplicate_sort(nums), expected);
}

#[test]
fn test_consistency_between_methods() {
let solution = setup();
let cases = vec![
vec![1, 2, 3, 1],
vec![1, 2, 3, 4],
vec![1, 1, 1, 3, 3, 4, 3, 2, 4, 2],
vec![0; 1],
vec![0, 0],
];
for nums in cases {
assert_eq!(
solution.contains_duplicate_set(nums.clone()),
solution.contains_duplicate_sort(nums)
);
}
}
}
Loading
Loading