diff --git a/rust/Backtracking/combinations_of_sum_k.rs b/rust/Backtracking/combinations_of_sum_k.rs new file mode 100644 index 0000000..4f2894d --- /dev/null +++ b/rust/Backtracking/combinations_of_sum_k.rs @@ -0,0 +1,41 @@ +pub fn combinations_of_sum_k(nums: Vec, target: i32) -> Vec> { + let mut res: Vec> = Vec::new(); + let mut combination: Vec = Vec::new(); + + dfs(&mut combination, 0, &nums, target, &mut res); + + res +} + +fn dfs( + combination: &mut Vec, + start_index: usize, + nums: &Vec, + target: i32, + res: &mut Vec> +) { + // 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; + } + + // Termination condition: If the target is less than 0, no more valid + // combinations can be created by adding it to the current combination. + if target < 0 { + return; + } + + // Starting from start_index, explore all combinations after adding nums[i]. + for i in start_index..nums.len() { + // Add the current number to create a new combination. + combination.push(nums[i]); + + // Recursively explore all paths that branch from this new combination. + dfs(combination, i, nums, target - nums[i], res); + + // Backtrack by removing the number we just added. + combination.pop(); + } +} \ No newline at end of file diff --git a/rust/Backtracking/find_all_permutations.rs b/rust/Backtracking/find_all_permutations.rs new file mode 100644 index 0000000..4a16eea --- /dev/null +++ b/rust/Backtracking/find_all_permutations.rs @@ -0,0 +1,37 @@ +pub fn find_all_permutations(nums: Vec) -> Vec> { + let mut res: Vec> = Vec::new(); + let mut candidate: Vec = Vec::new(); + let mut used: std::collections::HashSet = std::collections::HashSet::new(); + + backtrack(&nums, &mut candidate, &mut used, &mut res); + + res +} + +fn backtrack( + nums: &Vec, + candidate: &mut Vec, + used: &mut std::collections::HashSet, + res: &mut Vec> +) { + // If the current candidate is a complete permutation, add it to the result. + if candidate.len() == nums.len() { + res.push(candidate.clone()); + return; + } + + for &num in nums { + if !used.contains(&num) { + // Add 'num' to the current permutation and mark it as used. + candidate.push(num); + used.insert(num); + + // Recursively explore all branches using the updated permutation candidate. + backtrack(nums, candidate, used, res); + + // Backtrack by reversing the changes made. + candidate.pop(); + used.remove(&num); + } + } +} diff --git a/rust/Backtracking/find_all_subsets.rs b/rust/Backtracking/find_all_subsets.rs new file mode 100644 index 0000000..2cff516 --- /dev/null +++ b/rust/Backtracking/find_all_subsets.rs @@ -0,0 +1,32 @@ +pub fn find_all_subsets(nums: Vec) -> Vec> { + let mut res: Vec> = Vec::new(); + let mut curr_subset: Vec = Vec::new(); + + backtrack(0, &mut curr_subset, &nums, &mut res); + + res +} + +fn backtrack( + i: usize, + curr_subset: &mut Vec, + nums: &Vec, + res: &mut Vec> +) { + // Base case: if all elements have been considered, add the + // current subset to the output. + if i == nums.len() { + res.push(curr_subset.clone()); + 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); +} diff --git a/rust/Backtracking/n_queens.rs b/rust/Backtracking/n_queens.rs new file mode 100644 index 0000000..e62144d --- /dev/null +++ b/rust/Backtracking/n_queens.rs @@ -0,0 +1,54 @@ +pub fn n_queens(n: i32) -> i32 { + let mut res = 0; + let mut diagonals_set = std::collections::HashSet::new(); + let mut anti_diagonals_set = std::collections::HashSet::new(); + let mut cols_set = std::collections::HashSet::new(); + + dfs(0, &mut diagonals_set, &mut anti_diagonals_set, &mut cols_set, n, &mut res); + + res +} + +fn dfs( + r: i32, + diagonals_set: &mut std::collections::HashSet, + anti_diagonals_set: &mut std::collections::HashSet, + cols_set: &mut std::collections::HashSet, + n: i32, + res: &mut i32 +) { + // Termination condition: If we have reached the end of the rows, + // we've placed all 'n' queens. + if r == n { + *res += 1; + return; + } + + for c in 0..n { + let curr_diagonal = r - c; + let curr_anti_diagonal = r + c; + + // If there are queens on the current column, diagonal or + // anti-diagonal, skip this square. + if cols_set.contains(&c) || + diagonals_set.contains(&curr_diagonal) || + anti_diagonals_set.contains(&curr_anti_diagonal) { + continue; + } + + // Place the queen by marking the current column, diagonal, and + // anti-diagonal as occupied. + cols_set.insert(c); + diagonals_set.insert(curr_diagonal); + anti_diagonals_set.insert(curr_anti_diagonal); + + // Recursively move to the next row to continue placing queens. + dfs(r + 1, diagonals_set, anti_diagonals_set, cols_set, n, res); + + // Backtrack by removing the current column, diagonal, and + // anti-diagonal from the hash sets. + cols_set.remove(&c); + diagonals_set.remove(&curr_diagonal); + anti_diagonals_set.remove(&curr_anti_diagonal); + } +} diff --git a/rust/Backtracking/phone_keypad_combinations.rs b/rust/Backtracking/phone_keypad_combinations.rs new file mode 100644 index 0000000..23cc044 --- /dev/null +++ b/rust/Backtracking/phone_keypad_combinations.rs @@ -0,0 +1,54 @@ +use std::collections::HashMap; + +pub fn phone_keypad_combinations(digits: String) -> Vec { + if digits.is_empty() { + return Vec::new(); + } + + let mut keypad_map = HashMap::new(); + keypad_map.insert('2', "abc"); + keypad_map.insert('3', "def"); + keypad_map.insert('4', "ghi"); + keypad_map.insert('5', "jkl"); + keypad_map.insert('6', "mno"); + keypad_map.insert('7', "pqrs"); + keypad_map.insert('8', "tuv"); + keypad_map.insert('9', "wxyz"); + + let mut res: Vec = Vec::new(); + let mut curr_combination: Vec = Vec::new(); + + let digits_chars: Vec = digits.chars().collect(); + backtrack(0, &mut curr_combination, &digits_chars, &keypad_map, &mut res); + + res +} + +fn backtrack( + i: usize, + curr_combination: &mut Vec, + digits: &Vec, + keypad_map: &HashMap, + res: &mut Vec +) { + // 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; + } + + let digit = digits[i]; + if let Some(letters) = keypad_map.get(&digit) { + for letter in letters.chars() { + // Add the 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(); + } + } +}