diff --git a/rust/Hash Maps and Sets/geometric_sequence_triplets.rs b/rust/Hash Maps and Sets/geometric_sequence_triplets.rs new file mode 100644 index 0000000..d301867 --- /dev/null +++ b/rust/Hash Maps and Sets/geometric_sequence_triplets.rs @@ -0,0 +1,29 @@ +use std::collections::HashMap; + +fn geometric_sequence_triplets(nums: Vec, r: i32) -> i32 { + // Use 'HashMap' to ensure the default value of 0 is returned when + // accessing a key that doesn’t exist in the hash map. This effectively sets + // the default frequency of all elements to 0. + let mut left_map: HashMap = HashMap::new(); + let mut right_map: HashMap = HashMap::new(); + let mut count = 0; + // Populate 'right_map' with the frequency of each element in the array. + for &x in &nums { + *right_map.entry(x).or_insert(0) += 1; + } + // Search for geometric triplets that have x as the center. + for &x in &nums { + // Decrement the frequency of x in 'right_map' since x is now being + // processed and is no longer to the right. + *right_map.entry(x).or_insert(0) -= 1; + if x % r == 0 { + let left_count = *left_map.get(&(x / r)).unwrap_or(&0); + let right_count = *right_map.get(&(x * r)).unwrap_or(&0); + count += left_count * right_count; + } + // Increment the frequency of x in 'left_map' since it'll be a part of the + // left side of the array once we iterate to the next value of x. + *left_map.entry(x).or_insert(0) += 1; + } + count +} diff --git a/rust/Hash Maps and Sets/longest_chain_of_consecutive_numbers.rs b/rust/Hash Maps and Sets/longest_chain_of_consecutive_numbers.rs new file mode 100644 index 0000000..193d06c --- /dev/null +++ b/rust/Hash Maps and Sets/longest_chain_of_consecutive_numbers.rs @@ -0,0 +1,24 @@ +use std::collections::HashSet; + +fn longest_chain_of_consecutive_numbers(nums: Vec) -> i32 { + if nums.is_empty() { + return 0; + } + let num_set: HashSet = nums.into_iter().collect(); + let mut longest_chain = 0; + for num in &num_set { + // If the current number is the smallest number in its chain, search for + // the length of its chain + if !num_set.contains(&(num - 1)) { + let mut current_num = *num; + let mut current_chain = 1; + // Continue to find the next consecutive numbers in the chain + while num_set.contains(&(current_num + 1)) { + current_num += 1; + current_chain += 1; + } + longest_chain = longest_chain.max(current_chain); + } + } + longest_chain +} diff --git a/rust/Hash Maps and Sets/longest_chain_of_consecutive_numbers_brute_force.rs b/rust/Hash Maps and Sets/longest_chain_of_consecutive_numbers_brute_force.rs new file mode 100644 index 0000000..d7888ac --- /dev/null +++ b/rust/Hash Maps and Sets/longest_chain_of_consecutive_numbers_brute_force.rs @@ -0,0 +1,18 @@ +fn longest_chain_of_consecutive_numbers_brute_force(nums: Vec) -> i32 { + if nums.is_empty() { + return 0; + } + let mut longest_chain = 0; + // Look for chains of consecutive numbers that start from each number + for num in &nums { + let mut current_num = *num; + let mut current_chain = 1; + // Continue to find the next consecutive numbers in the chain + while nums.contains(&(current_num + 1)) { + current_num += 1; + current_chain += 1; + } + longest_chain = longest_chain.max(current_chain); + } + longest_chain +} diff --git a/rust/Hash Maps and Sets/pair_sum_unsorted.rs b/rust/Hash Maps and Sets/pair_sum_unsorted.rs new file mode 100644 index 0000000..1baf8b0 --- /dev/null +++ b/rust/Hash Maps and Sets/pair_sum_unsorted.rs @@ -0,0 +1,13 @@ +use std::collections::HashMap; + +pub fn pair_sum_unsorted(nums: &[i32], target: i32) -> Vec { + let mut hashmap: HashMap = HashMap::new(); + for (i, &x) in nums.iter().enumerate() { + let complement = target - x; + if let Some(&complement_idx) = hashmap.get(&complement) { + return vec![complement_idx, i as i32]; + } + hashmap.insert(x, i as i32); + } + vec![] +} diff --git a/rust/Hash Maps and Sets/pair_sum_unsorted_two_pass.rs b/rust/Hash Maps and Sets/pair_sum_unsorted_two_pass.rs new file mode 100644 index 0000000..c95c944 --- /dev/null +++ b/rust/Hash Maps and Sets/pair_sum_unsorted_two_pass.rs @@ -0,0 +1,19 @@ +use std::collections::HashMap; + +fn pair_sum_unsorted_two_pass(nums: Vec, target: i32) -> Vec { + let mut num_map: HashMap = HashMap::new(); + // First pass: Populate the hash map with each number and its index + for (i, num) in nums.iter().enumerate() { + num_map.insert(*num, i); + } + // Second pass: Check for each number's complement in the hash map + for (i, num) in nums.iter().enumerate() { + let complement = target - num; + if let Some(&complement_index) = num_map.get(&complement) { + if complement_index != i { + return vec![i, complement_index]; + } + } + } + vec![] +} diff --git a/rust/Hash Maps and Sets/verify_sudoku_board.rs b/rust/Hash Maps and Sets/verify_sudoku_board.rs new file mode 100644 index 0000000..781242d --- /dev/null +++ b/rust/Hash Maps and Sets/verify_sudoku_board.rs @@ -0,0 +1,35 @@ +use std::collections::HashSet; + +fn verify_sudoku_board(board: Vec>) -> bool { + // Create hash sets for each row, column, and subgrid to keep + // track of numbers previously seen on any given row, column, or + // subgrid. + let mut row_sets: Vec> = vec![HashSet::new(); 9]; + let mut column_sets: Vec> = vec![HashSet::new(); 9]; + let mut subgrid_sets: Vec>> = vec![vec![HashSet::new(); 3]; 3]; + for r in 0..9 { + for c in 0..9 { + let num = board[r][c]; + if num == 0 { + continue; + } + // Check if 'num' has been seen in the current row, + // column, or subgrid. + if row_sets[r].contains(&num) { + return false; + } + if column_sets[c].contains(&num) { + return false; + } + if subgrid_sets[r / 3][c / 3].contains(&num) { + return false; + } + // If we passed the above checks, mark this value as seen + // by adding it to its corresponding hash sets. + row_sets[r].insert(num); + column_sets[c].insert(num); + subgrid_sets[r / 3][c / 3].insert(num); + } + } + true +} diff --git a/rust/Hash Maps and Sets/zero_striping.rs b/rust/Hash Maps and Sets/zero_striping.rs new file mode 100644 index 0000000..fb10d88 --- /dev/null +++ b/rust/Hash Maps and Sets/zero_striping.rs @@ -0,0 +1,45 @@ +fn zero_striping(matrix: &mut Vec>) { + if matrix.is_empty() || matrix[0].is_empty() { + return; + } + let m = matrix.len(); + let n = matrix[0].len(); + // Check if the first row initially contains a zero + let first_row_has_zero = matrix[0].iter().any(|&x| x == 0); + // Check if the first column initially contains a zero + let first_col_has_zero = matrix.iter().any(|row| row[0] == 0); + // Use the first row and column as markers. If an element in the + // submatrix is zero, mark its corresponding row and column in the + // first row and column as 0. + for r in 1..m { + for c in 1..n { + if matrix[r][c] == 0 { + matrix[0][c] = 0; + matrix[r][0] = 0; + } + } + } + // Update the submatrix using the markers in the first row and + // column + for r in 1..m { + for c in 1..n { + if matrix[0][c] == 0 || matrix[r][0] == 0 { + matrix[r][c] = 0; + } + } + } + // If the first row had a zero initially, set all elements in the first + // row to zero + if first_row_has_zero { + for c in 0..n { + matrix[0][c] = 0; + } + } + // If the first column had a zero initially, set all elements in + // the first column to zero + if first_col_has_zero { + for r in 0..m { + matrix[r][0] = 0; + } + } +} diff --git a/rust/Hash Maps and Sets/zero_striping_hash_sets.rs b/rust/Hash Maps and Sets/zero_striping_hash_sets.rs new file mode 100644 index 0000000..d7daa9e --- /dev/null +++ b/rust/Hash Maps and Sets/zero_striping_hash_sets.rs @@ -0,0 +1,31 @@ +use std::collections::HashSet; + +fn zero_striping_hash_sets(matrix: &mut Vec>) { + if matrix.is_empty() || matrix[0].is_empty() { + return; + } + let m = matrix.len(); + let n = matrix[0].len(); + let mut zero_rows = HashSet::new(); + let mut zero_cols = HashSet::new(); + // Pass 1: Traverse through the matrix to identify the rows and + // columns containing zeros and store their indexes in the + // appropriate hash sets. + for r in 0..m { + for c in 0..n { + if matrix[r][c] == 0 { + zero_rows.insert(r); + zero_cols.insert(c); + } + } + } + // Pass 2: Set any cell in the matrix to zero if its row index is + // in 'zero_rows' or its column index is in 'zero_cols'. + for r in 0..m { + for c in 0..n { + if zero_rows.contains(&r) || zero_cols.contains(&c) { + matrix[r][c] = 0; + } + } + } +} diff --git a/rust/Two Pointers/largest_container_brute_force.rs b/rust/Two Pointers/largest_container_brute_force.rs new file mode 100644 index 0000000..70bd0ea --- /dev/null +++ b/rust/Two Pointers/largest_container_brute_force.rs @@ -0,0 +1,13 @@ +fn largest_container_brute_force(heights: Vec) -> i32 { + let n = heights.len(); + let mut max_water = 0; + + // Find the maximum amount of water stored between all pairs of lines. + for i in 0..n { + for j in (i + 1)..n { + let water = heights[i].min(heights[j]) * (j as i32 - i as i32); + max_water = max_water.max(water); + } + } + max_water +} diff --git a/rust/Two Pointers/next_lexicographical_sequence.rs b/rust/Two Pointers/next_lexicographical_sequence.rs new file mode 100644 index 0000000..6162e97 --- /dev/null +++ b/rust/Two Pointers/next_lexicographical_sequence.rs @@ -0,0 +1,27 @@ +fn next_lexicographical_sequence(s: &str) -> String { + let mut letters: Vec = s.chars().collect(); + // Locate the pivot, which is the first character from the right that breaks + // non-increasing order. Start searching from the second-to-last position. + let mut pivot = letters.len() as i32 - 2; + while pivot >= 0 && letters[pivot as usize] >= letters[(pivot + 1) as usize] { + pivot -= 1; + } + // If pivot is not found, the string is already in its largest permutation. In + // this case, reverse the string to obtain the smallest permutation. + if pivot == -1 { + letters.reverse(); + return letters.into_iter().collect(); + } + let pivot = pivot as usize; + // Find the rightmost successor to the pivot. + let mut rightmost_successor = letters.len() - 1; + while letters[rightmost_successor] <= letters[pivot] { + rightmost_successor -= 1; + } + // Swap the rightmost successor with the pivot to increase the lexicographical + // order of the suffix. + letters.swap(pivot, rightmost_successor); + // Reverse the suffix after the pivot to minimize its permutation. + letters[(pivot + 1)..].reverse(); + letters.into_iter().collect() +} diff --git a/rust/Two Pointers/pair_sum_sorted_brute_force.rs b/rust/Two Pointers/pair_sum_sorted_brute_force.rs new file mode 100644 index 0000000..de77dd8 --- /dev/null +++ b/rust/Two Pointers/pair_sum_sorted_brute_force.rs @@ -0,0 +1,12 @@ +fn pair_sum_sorted_brute_force(nums: Vec, target: i32) -> Vec { + let n = nums.len(); + + for i in 0..n { + for j in (i + 1)..n { + if nums[i] + nums[j] == target { + return vec![i as i32, j as i32]; + } + } + } + vec![] +} diff --git a/rust/Two Pointers/triplet_sum_brute_force.rs b/rust/Two Pointers/triplet_sum_brute_force.rs new file mode 100644 index 0000000..20a3971 --- /dev/null +++ b/rust/Two Pointers/triplet_sum_brute_force.rs @@ -0,0 +1,23 @@ +use std::collections::HashSet; + +fn triplet_sum_brute_force(nums: Vec) -> Vec> { + let n = nums.len(); + // Use a hash set to ensure we don't add duplicate triplets. + let mut triplets = HashSet::new(); + + // Iterate through the indexes of all triplets. + for i in 0..n {w + for j in (i + 1)..n { + for k in (j + 1)..n { + if nums[i] + nums[j] + nums[k] == 0 { + // Sort the triplet before including it in the hash set. + let mut triplet = vec![nums[i], nums[j], nums[k]]; + triplet.sort(); + triplets.insert(triplet); + } + } + } + } + + triplets.into_iter().collect() +}