diff --git a/0001-two-sum.rs b/0001-two-sum.rs new file mode 100644 index 0000000..910ccdf --- /dev/null +++ b/0001-two-sum.rs @@ -0,0 +1,27 @@ +use std::collections::HashMap; + +pub fn two_sum(nums: Vec, target: i32) -> Vec { + let mut m = HashMap::new(); + for (i, num) in nums.iter().enumerate() { + match m.get(&(target - num)) { + Some(&j) => return vec![j, i as i32], + None => m.insert(num, i as i32), + }; + } + return vec![]; +} + +#[cfg(test)] +mod two_sum { + use super::two_sum; + + #[test] + pub fn finds_index_if_exists() { + assert_eq!(two_sum(vec![2, 7, 11, 15], 9), vec![0, 1]); + assert_eq!(two_sum(vec![2, 7, 11, 15], 18), vec![1, 2]); + } + #[test] + pub fn no_solution() { + assert_eq!(two_sum(vec![2, 7, 11, 15], 19), vec![]); + } +} diff --git a/0002-add-two-numbers.rs b/0002-add-two-numbers.rs new file mode 100644 index 0000000..cd5ae74 --- /dev/null +++ b/0002-add-two-numbers.rs @@ -0,0 +1,58 @@ +use utils::list_node::ListNode; + +pub fn add_two_numbers( + l1: Option>, + l2: Option>, +) -> Option> { + let (mut p, mut q) = (l1.as_ref(), l2.as_ref()); + let mut dummy_head = Box::new(ListNode::new(0)); + let mut curr = &mut dummy_head; + let mut carry = 0; + while p.is_some() || q.is_some() { + let x = p.map_or(0, |node| node.as_ref().val); + let y = q.map_or(0, |node| node.as_ref().val); + let sum = carry + x + y; + carry = sum / 10; + + curr.next = Some(Box::new(ListNode::new(sum % 10))); + + curr = curr.next.as_mut().unwrap(); + p = p.map_or(None, |node| node.next.as_ref()); + q = q.map_or(None, |node| node.next.as_ref()); + } + if carry != 0 { + curr.next = Some(Box::new(ListNode::new(1))); + } + + dummy_head.next +} + +#[cfg(test)] +mod add_two_numbers { + use super::add_two_numbers; + use utils::list_node::{linked_list_to_vector, vector_to_linked_list}; + + fn test(a: Vec, b: Vec, expected: Vec) { + let l1 = vector_to_linked_list(a); + let l2 = vector_to_linked_list(b); + let sum = add_two_numbers(l1, l2); + assert_eq!(linked_list_to_vector(sum), expected); + } + + #[test] + fn all_lengths_equal() { + test(vec![2, 4, 3], vec![5, 6, 4], vec![7, 0, 8]); + test(vec![1], vec![2], vec![3]); + test(vec![], vec![], vec![]); + } + #[test] + fn output_is_longer() { + test(vec![2, 4, 7], vec![5, 6, 4], vec![7, 0, 2, 1]); + } + #[test] + fn unequal_input_lengths() { + test(vec![2], vec![5, 6, 4], vec![7, 6, 4]); + test(vec![], vec![5, 6, 4], vec![5, 6, 4]); + test(vec![5, 6, 4], vec![1, 0], vec![6, 6, 4]); + } +} diff --git a/0021-merge-two-sorted-lists.rs b/0021-merge-two-sorted-lists.rs new file mode 100644 index 0000000..50cef5a --- /dev/null +++ b/0021-merge-two-sorted-lists.rs @@ -0,0 +1,45 @@ +use utils::list_node::ListNode; + +type Node = Option>; +pub fn merge_two_lists(l1: Node, l2: Node) -> Node { + let mut result = Box::new(ListNode::new(0)); + let (mut p, mut q) = (l1.as_ref(), l2.as_ref()); + let mut iter = &mut result; + while p.is_some() && q.is_some() { + let (a, b) = (p.unwrap(), q.unwrap()); + if a.val < b.val { + iter.next = p.cloned(); + p = a.next.as_ref(); + } else { + iter.next = q.cloned(); + q = b.next.as_ref(); + } + iter = iter.next.as_mut()?; + } + iter.next = if p.is_some() { p.cloned() } else { q.cloned() }; + println!("{:p}", result.next?); + println!("{:p}", l1?); + println!("{:p}", l2?); + None + // result.next +} + +#[cfg(test)] +mod merge_two_lists { + use super::merge_two_lists; + use utils::list_node::{linked_list_to_vector, vector_to_linked_list}; + + fn test(a: Vec, b: Vec, expected: Vec) { + let l1 = vector_to_linked_list(a); + let l2 = vector_to_linked_list(b); + let merged = merge_two_lists(l1, l2); + assert_eq!(linked_list_to_vector(merged), expected); + } + + #[test] + fn it_works() { + test(vec![1, 2, 4], vec![1, 3, 4], vec![1, 1, 2, 3, 4]); + test(vec![2], vec![1], vec![1, 2]); + test(vec![], vec![], vec![]); + } +} diff --git a/0026-remove-duplicates-from-sorted-array.rs b/0026-remove-duplicates-from-sorted-array.rs new file mode 100644 index 0000000..42302dc --- /dev/null +++ b/0026-remove-duplicates-from-sorted-array.rs @@ -0,0 +1,53 @@ +pub fn remove_duplicates(nums: &mut Vec) -> i32 { + if nums.is_empty() { + return 0 as i32; + } + + let mut l: usize = 0; + for r in 0..nums.len() { + if nums[r] != nums[l] { + l += 1; + nums[l] = nums[r]; + } + } + l += 1; + l as i32 +} + +#[cfg(test)] +mod remove_duplicates { + use super::remove_duplicates; + + #[test] + pub fn no_duplicates() { + let mut nums = vec![3, 5, 7, 9]; + let len = remove_duplicates(&mut nums); + assert_eq!(len, 4); + let expected = vec![3, 5, 7, 9]; + assert_eq!(&nums[..len as usize], &expected[..]); + } + #[test] + pub fn some_are_duplicates() { + let mut nums = vec![0, 0, 1, 1, 1, 2, 2, 3, 3, 4]; + let len = remove_duplicates(&mut nums); + assert_eq!(len, 5); + let expected = vec![0, 1, 2, 3, 4]; + assert_eq!(&nums[..len as usize], &expected[..]); + } + #[test] + pub fn all_are_duplicates() { + let mut nums = vec![3, 3, 3, 4, 4, 4]; + let len = remove_duplicates(&mut nums); + assert_eq!(len, 2); + let expected = vec![3, 4]; + assert_eq!(&nums[..len as usize], &expected[..]); + } + #[test] + pub fn empty_input() { + let mut nums = vec![]; + let len = remove_duplicates(&mut nums); + assert_eq!(len, 0); + let expected = vec![]; + assert_eq!(&nums[..len as usize], &expected[..]); + } +} diff --git a/0027-remove-element.rs b/0027-remove-element.rs new file mode 100644 index 0000000..4a4ee62 --- /dev/null +++ b/0027-remove-element.rs @@ -0,0 +1,46 @@ +pub fn remove_element(nums: &mut Vec, val: i32) -> i32 { + let mut left: usize = 0; + for i in 0..nums.len() { + if nums[i] != val { + nums[left] = nums[i]; + left += 1; + } + } + left as i32 +} + +#[cfg(test)] +mod remove_element { + use super::remove_element; + + #[test] + pub fn no_instance_of_val() { + let mut nums = vec![3, 2, 2, 3]; + let len = remove_element(&mut nums, 0); + assert_eq!(len, 4); + let expected = vec![3, 2, 2, 3]; + assert_eq!(&nums[..len as usize], &expected[..]); + } + #[test] + pub fn some_instances_of_val() { + let mut nums = vec![3, 2, 2, 3]; + let len = remove_element(&mut nums, 3); + assert_eq!(len, 2); + let expected = vec![2, 2]; + assert_eq!(&nums[..len as usize], &expected[..]); + + let mut nums = vec![0, 1, 2, 2, 3, 0, 4, 2]; + let len = remove_element(&mut nums, 2); + assert_eq!(len, 5); + let expected = vec![0, 1, 3, 0, 4]; + assert_eq!(&nums[..len as usize], &expected[..]); + } + #[test] + pub fn all_instances_of_val() { + let mut nums = vec![3, 3, 3]; + let len = remove_element(&mut nums, 3); + assert_eq!(len, 0); + let expected = vec![]; + assert_eq!(&nums[..len as usize], &expected[..]); + } +} diff --git a/1091-shortest-path-in-binary-matrix.rs b/1091-shortest-path-in-binary-matrix.rs new file mode 100644 index 0000000..233210c --- /dev/null +++ b/1091-shortest-path-in-binary-matrix.rs @@ -0,0 +1,277 @@ +struct Solution; + +use std::cmp::Ordering; +use std::collections::{BinaryHeap, HashMap, HashSet}; + +type Position = (usize, usize); +type Grid = Vec>; +type Path = Vec; + +#[derive(Debug, Eq, PartialEq)] +struct Node { + priority: i32, + position: Position, +} + +impl Ord for Node { + fn cmp(&self, other: &Node) -> Ordering { + other + .priority + .cmp(&self.priority) + .then_with(|| self.position.cmp(&other.position)) + } +} + +impl PartialOrd for Node { + fn partial_cmp(&self, other: &Node) -> Option { + Some(self.cmp(other)) + } +} + +struct AStar { + grid: Grid, +} + +impl AStar { + pub fn new(grid: Grid) -> Self { + Self { grid } + } + + pub fn find_path(&self, start: Position, goal: Position) -> Option { + let mut distances: HashMap = HashMap::new(); + let mut visited: HashSet = HashSet::new(); + let mut frontier = BinaryHeap::new(); + + frontier.push(Node { + priority: 0, + position: start, + }); + distances.insert(start, 0); + + let mut came_from: HashMap = HashMap::new(); + while let Some(node) = frontier.pop() { + let current = node.position; + if visited.contains(¤t) { + continue; + } + if current == goal { + let path_followed = Self::reconstruct_path(start, goal, came_from); + return Some(path_followed); + } + + visited.insert(current); + for next in self.get_successors(current) { + let priority = distances[¤t] + 1 + Self::heuristic(goal, next); + frontier.push(Node { + priority, + position: next, + }); + + if !distances.contains_key(&next) || distances[¤t] + 1 < distances[&next] { + distances.insert(next, distances[¤t] + 1); + came_from.insert(next, current); + } + } + } + + None + } + + fn get_successors(&self, from: Position) -> Vec { + let (m, n) = (self.grid.len(), self.grid[0].len()); + let (rr, cc) = from; + + let mut successors = Vec::new(); + for (dr, dc) in DIRECTIONS { + let r = match (rr, dr) { + (0, -1) => continue, + _ => ((rr as i32) + dr) as usize, + }; + let c = match (cc, dc) { + (0, -1) => continue, + _ => ((cc as i32) + dc) as usize, + }; + if r >= m || c >= n || self.grid[r][c] == 1 { + continue; + } + let successor: Position = (r, c); + successors.push(successor); + } + successors + } + + fn reconstruct_path( + start: Position, + goal: Position, + came_from: HashMap, + ) -> Path { + let mut current = goal; + let mut reverse_path = vec![current]; + while current != start { + current = came_from[¤t]; + reverse_path.push(current); + } + let path_followed: Vec<_> = reverse_path.iter().cloned().rev().collect(); + path_followed + } + + fn heuristic(goal: Position, pos: Position) -> i32 { + let (r, c) = pos; + let (m, n) = goal; + std::cmp::max(m - r, n - c) as i32 + } + + pub fn print_path(&self, path: &Path) { + let mut output: Vec> = Vec::new(); + for row in &self.grid { + let mut p = vec![]; + for col in row { + p.push(format!("{} ", if *col == 1 { "⬛" } else { "🏼" })); + } + output.push(p); + } + for (r, c) in path { + output[*r][*c] = String::from("💠 "); + } + for row in output { + for col in row { + print!("{}", col); + } + print!("\n"); + } + // println!("{:?}", path); + } +} + +const DIRECTIONS: &[(i32, i32)] = &[ + (-1, -1), + (-1, 0), + (-1, 1), + (0, -1), + (0, 1), + (1, -1), + (1, 0), + (1, 1), +]; + +impl Solution { + pub fn shortest_path_binary_matrix(grid: Grid) -> i32 { + let (m, n) = (grid.len(), grid[0].len()); + if grid[0][0] == 1 || grid[m - 1][n - 1] == 1 { + return -1; + } + + let astar = AStar::new(grid); + let start: Position = (0, 0); + let goal: Position = (m - 1, n - 1); + match astar.find_path(start, goal) { + Some(path) => { + astar.print_path(&path); + path.len() as i32 + } + None => -1, + } + } +} + +fn main() { + let grids = vec![ + vec![ + vec![0, 0, 0, 1, 0, 0, 1, 0], + vec![0, 0, 0, 0, 0, 0, 0, 0], + vec![1, 0, 0, 1, 1, 0, 1, 0], + vec![0, 1, 1, 1, 0, 0, 0, 0], + vec![0, 0, 0, 0, 0, 1, 1, 1], + vec![1, 0, 1, 0, 0, 0, 0, 0], + vec![1, 1, 0, 0, 0, 1, 0, 0], + vec![0, 0, 0, 0, 0, 1, 0, 0], + ], + vec![vec![0, 0, 0], vec![1, 1, 0], vec![1, 1, 0]], + vec![ + vec![0, 0, 1, 0, 1, 1], + vec![1, 0, 0, 1, 0, 0], + vec![0, 1, 0, 1, 0, 0], + vec![1, 0, 1, 0, 0, 0], + vec![0, 1, 0, 1, 0, 0], + vec![0, 0, 0, 0, 0, 0], + ], + vec![ + vec![ + 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, + ], + vec![ + 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, + ], + vec![ + 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, + ], + vec![ + 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, + ], + vec![ + 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, + ], + vec![ + 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, + ], + vec![ + 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, + ], + vec![ + 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, + ], + vec![ + 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, + ], + vec![ + 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, + ], + vec![ + 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, + ], + vec![ + 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, + ], + vec![ + 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, + ], + vec![ + 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, + ], + vec![ + 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, + ], + vec![ + 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, + ], + vec![ + 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, + ], + vec![ + 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, + ], + vec![ + 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, + ], + vec![ + 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, + ], + vec![ + 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, + ], + vec![ + 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, + ], + vec![ + 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, + ], + vec![ + 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, + ], + ], + ]; + for grid in grids { + let result = Solution::shortest_path_binary_matrix(grid); + println!("result: {:?}", result); + } +} diff --git a/814-binary-tree-pruning.rs b/814-binary-tree-pruning.rs new file mode 100644 index 0000000..8fdf17d --- /dev/null +++ b/814-binary-tree-pruning.rs @@ -0,0 +1,50 @@ +mod tree; +use tree::*; + +use std::cell::RefCell; +use std::rc::Rc; + +struct Solution; +impl Solution { + pub fn prune_tree(root: Option>>) -> Option>> { + match root { + None => None, + Some(ref r) => { + let left = r.borrow().left.as_ref().map_or(None, |x| Some(x.clone())); + r.borrow_mut().left = Self::prune_tree(left); + + let right = r.borrow().right.as_ref().map_or(None, |x| Some(x.clone())); + r.borrow_mut().right = Self::prune_tree(right); + + if r.borrow().val == 0 && r.borrow().left.is_none() && r.borrow().right.is_none() { + return None; + } + root + } + } + } +} + +fn main() { + // let root = Some(Rc::new(RefCell::new(TreeNode::new(1)))); + // let right = Some(Rc::new(RefCell::new(TreeNode::new(0)))); + // right.as_ref().unwrap().borrow_mut().left = Some(Rc::new(RefCell::new(TreeNode::new(0)))); + // right.as_ref().unwrap().borrow_mut().right = Some(Rc::new(RefCell::new(TreeNode::new(1)))); + // root.as_ref().unwrap().borrow_mut().right = right; + let root = tree![1, null, 0, 0, 1]; + println!("{:#?}", root); + let result = Solution::prune_tree(root); + println!("{:#?}", result); +} + +// ``` java +// public TreeNode pruneTree(TreeNode root) { +// if ( root == null ) return null; + +// root.left = pruneTree (root.left); +// root.right = pruneTree (root.right); + +// if ( root.val == 0 && root.left == null && root.right == null ) return null; +// return root; +// } +// ```