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
40 changes: 40 additions & 0 deletions rust/Backtracking/combination_of_sum.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
fn dfs(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

combination_of_sum.rs -> combinations_of_sum_k.rs

combination: &mut Vec<u32>,
start_index: usize,
nums: &[u32],
target: u32,
res: &mut Vec<Vec<u32>>,
) {
// Termination condition: If the target is equal to 0, we found a combination that sums to 'k'
if target == 0 {
res.push(combination.clone());
return;
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add the rust equivalent below
image


// Explore all combinations starting from 'start_index'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try to keep the comments and the logic structure the same as Python

for i in start_index..nums.len() {
let num = nums[i];

// If current number is greater than the remaining target, no need to proceed (early stopping)
if num > target {
break; // this is where early stop occurs
// since nums are ordered no need to check the others (there are > target)
}

// Add the current number to create a new combination
combination.push(num);
// Recursively explore all paths that branch from this new combination
dfs(combination, i, nums, target - num, res); // Safe subtraction: target >= num
// Backtrack by removing the number we just added
combination.pop();
}
}

fn combinations_of_sum_k(nums: &[u32], target: u32) -> Vec<Vec<u32>> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please order this function first, before the dfs function

let mut sorted_nums = nums.to_vec();
sorted_nums.sort_unstable(); // Sort the numbers to allow early stopping
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove the sorting. We'd like to keep it consistent with the python solutions, which don't do any sorting here.

let mut combination = Vec::new();
let mut res = Vec::new();
dfs(&mut combination, 0, &sorted_nums, target, &mut res);
res
}
19 changes: 19 additions & 0 deletions rust/Backtracking/find_all_permuations.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
fn backtrack(nums: &mut Vec<i32>, start: usize, res: &mut Vec<Vec<i32>>) {
// if current candidate is a complete permutation add it to the result
if start == nums.len() {
res.push(nums.clone()); // unavoidable here unless we return Vec<&[i32]>
return;
}
for i in start..nums.len() {
nums.swap(start, i);
backtrack(nums, start + 1, res);
nums.swap(start, i); // backtrack
}
}

fn find_all_permutations(nums: &[i32]) -> Vec<Vec<i32>> {
let mut res = Vec::new();
let mut nums = nums.to_vec();
backtrack(&mut nums, 0, &mut res);
res
}
19 changes: 19 additions & 0 deletions rust/Backtracking/find_all_subsets.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
fn backtrack(i: usize, curr_subset: &mut Vec<i32>, nums: &[i32], res: &mut Vec<Vec<i32>>) {
// base case : if all elements have been considered, add the current subset to res
if i == nums.len() {
res.push(curr_subset.clone()); // cannot push curr_subset (it is used afterward) so we push a clone of it
return;
}
// include the current element and recursively explore all paths that branch from this subset
curr_subset.push(nums[i]);
backtrack(i + 1, curr_subset, nums, res);
// exclude the current element and recursively explore all paths that branch from this subset
curr_subset.pop();
backtrack(i + 1, curr_subset, nums, res);
}

fn find_all_subsets(nums: &[i32]) -> Vec<Vec<i32>> {
let mut res = Vec::new();
backtrack(0, &mut vec![], nums, &mut res);
res
}
57 changes: 57 additions & 0 deletions rust/Backtracking/n_queens.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
use std::collections::HashSet;

fn dfs(
row: i32,
cols: &mut HashSet<i32>,
diagonals: &mut HashSet<i32>,
anti_diagonals: &mut HashSet<i32>,
n: i32,
count: &mut i32,
) {
// If we reach the end, all queens are placed successfully
if row == n {
*count += 1;
return;
}

for col in 0..n {
let diag = row - col;
let anti_diag = row + col;

// Check if the position is safe
if cols.contains(&col) || diagonals.contains(&diag) || anti_diagonals.contains(&anti_diag) {
continue;
}

// Choose: place the queen
cols.insert(col);
diagonals.insert(diag);
anti_diagonals.insert(anti_diag);

// Explore
dfs(row + 1, cols, diagonals, anti_diagonals, n, count);

// Unchoose (backtrack): remove the queen
cols.remove(&col);
diagonals.remove(&diag);
anti_diagonals.remove(&anti_diag);
}
}

fn n_queens(n: i32) -> i32 {
let mut cols = HashSet::new();
let mut diagonals = HashSet::new();
let mut anti_diagonals = HashSet::new();
let mut count = 0;

dfs(
0,
&mut cols,
&mut diagonals,
&mut anti_diagonals,
n,
&mut count,
);

count
}
56 changes: 56 additions & 0 deletions rust/Backtracking/phone_keypad_combinations.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
use std::collections::HashMap;

fn backtrack(
i: usize,
curr_combination: &mut Vec<char>,
digits: &[char],
keypad_map: &HashMap<char, &str>,
res: &mut Vec<String>,
) {
// Termination condition: if all digits have been considered
// Add the current combination to the output list
if curr_combination.len() == digits.len() {
res.push(curr_combination.iter().collect());
return;
}

// PYTHON = for letter in keypad_map[digits[i]]...
if let Some(&digit) = digits.get(i) {
if let Some(letters) = keypad_map.get(&digit) {
for letter in letters.chars() {
// Add current letter
curr_combination.push(letter);
// Recursively explore all paths that branch from this combination.
backtrack(i + 1, curr_combination, digits, keypad_map, res);
// Backtrack by removing the letter we just added.
curr_combination.pop();
}
}
}
}

fn phone_keypad_combinations(digits: &str) -> Vec<String> {
let index = 0;
let mut curr_combination = Vec::new();
let digits_chars: Vec<char> = digits.chars().collect(); // collect chars once
let keypad_map = HashMap::from([
('2', "abc"),
('3', "def"),
('4', "ghi"),
('5', "jkl"),
('6', "mno"),
('7', "pqrs"),
('8', "tuv"),
('9', "wxyz"),
]);
let mut res = Vec::new();

backtrack(
index,
&mut curr_combination,
&digits_chars,
&keypad_map,
&mut res,
);
res
}