├── .github └── workflows │ └── test.yml ├── .gitignore ├── .rustfmt.toml ├── Cargo.toml ├── LICENSE ├── README.md ├── logo.png └── src ├── binarysearch ├── minimum_bracket_addition.rs └── mod.rs ├── leetcode ├── challenge │ ├── break_palindrome.rs │ ├── calculate_minimum_hp.rs │ ├── can_partition_k_subsets.rs │ ├── cherry_pickup.rs │ ├── find_max_consecutive_ones.rs │ ├── intersect.rs │ ├── is_valid_palindrome.rs │ ├── longest_common_subsequence.rs │ ├── max_length.rs │ ├── max_sub_array_len.rs │ ├── minmax_gas_dist.rs │ ├── mod.rs │ ├── moves_to_chessboard.rs │ ├── num_distinct.rs │ ├── num_unique_emails.rs │ ├── shortest_distance.rs │ ├── shortest_path.rs │ ├── sort_array_by_parity_ii.rs │ ├── spiral_order.rs │ ├── split_list_to_parts.rs │ ├── tictactoe.rs │ └── tribonacci.rs ├── contest │ ├── biweekly_62.rs │ ├── biweekly_63.rs │ ├── mod.rs │ ├── weekly_261.rs │ ├── weekly_262.rs │ └── weekly_263.rs ├── interview │ ├── amazon │ │ ├── connect_sticks.rs │ │ ├── find_circle_num.rs │ │ ├── first_uniq_char.rs │ │ ├── high_five.rs │ │ ├── is_robot_bounded.rs │ │ ├── maximum_units.rs │ │ ├── minimum_cost.rs │ │ ├── mod.rs │ │ ├── reorder_log_files.rs │ │ ├── search.rs │ │ ├── suggested_products.rs │ │ └── sum_even_grandparent.rs │ ├── mod.rs │ ├── robinhood │ │ ├── alert_names.rs │ │ └── mod.rs │ └── uber │ │ ├── mod.rs │ │ └── num_buses_to_destination.rs ├── mod.rs ├── problem │ ├── add_operators.rs │ ├── broken_calc.rs │ ├── bst_from_preorder.rs │ ├── can_complete_circuit.rs │ ├── can_construct.rs │ ├── can_three_parts_equal_sum.rs │ ├── can_visit_all_rooms.rs │ ├── climb_stairs.rs │ ├── coin_change.rs │ ├── contain_virus.rs │ ├── count_binary_substrings.rs │ ├── course-schedule.rs │ ├── course-schedule_two.rs │ ├── diameter_of_binary_tree.rs │ ├── dot_product.rs │ ├── erase_overlap_intervals.rs │ ├── exist.rs │ ├── find_duplicates.rs │ ├── find_least_num_of_unique_ints.rs │ ├── find_min_arrow_shots.rs │ ├── find_poisoned_duration.rs │ ├── find_words.rs │ ├── get_number_of_backlog_orders.rs │ ├── guess_number.rs │ ├── implement_trie_prefix_tree.rs │ ├── inorder_traversal.rs │ ├── interval_intersection.rs │ ├── is_anagram.rs │ ├── is_cousins.rs │ ├── is_good_array.rs │ ├── is_same_tree.rs │ ├── island_perimeter.rs │ ├── k_closest.rs │ ├── kth_smallest.rs │ ├── largest_divisible_subset.rs │ ├── left_most_column_with_one.rs │ ├── longest_palindrome_subseq.rs │ ├── max_area_of_island.rs │ ├── max_level_sum.rs │ ├── max_profit.rs │ ├── max_profit2.rs │ ├── max_uncrossed_lines.rs │ ├── merge.rs │ ├── min_area.rs │ ├── min_distance.rs │ ├── min_eating_speed.rs │ ├── min_knight_moves.rs │ ├── min_meeting_rooms.rs │ ├── min_stone_sum.rs │ ├── min_transfers.rs │ ├── mod.rs │ ├── next_greater_element.rs │ ├── next_permutation.rs │ ├── num_islands.rs │ ├── num_of_subarrays.rs │ ├── num_subarray_product_less_than_k.rs │ ├── num_subarrays_with_sum.rs │ ├── order_of_largest_plus_sign.rs │ ├── path_sum_3.rs │ ├── perfect_squares.rs │ ├── pseudo_palindromic_paths.rs │ ├── range_bitwise_and.rs │ ├── restore_array.rs │ ├── restore_ip_addresses.rs │ ├── rob.rs │ ├── rotate_the_box.rs │ ├── search_range.rs │ ├── solve_n_queens.rs │ ├── solve_sudoku.rs │ ├── stock_span.rs │ ├── sum_even_grandparent.rs │ ├── total_n_queens.rs │ ├── trap.rs │ ├── two_sum.rs │ ├── unique_paths.rs │ └── zigzag_level_order.rs ├── top_interview │ ├── array_and_string │ │ ├── group_anagrams.rs │ │ ├── increasing_triplet.rs │ │ ├── length_of_longest_substring.rs │ │ ├── longest_palindrome.rs │ │ ├── mod.rs │ │ └── set_zeroes.rs │ ├── dynamic_programming │ │ ├── can_jump.rs │ │ └── mod.rs │ ├── linked_list │ │ ├── add_two_numbers.rs │ │ └── mod.rs │ ├── mod.rs │ ├── others │ │ ├── majority_element.rs │ │ └── mod.rs │ └── sorting │ │ ├── mod.rs │ │ └── sort_colors.rs └── util │ ├── mod.rs │ └── vec_vec.rs └── main.rs /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: test 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | env: 10 | CARGO_TERM_COLOR: always 11 | 12 | jobs: 13 | test: 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - uses: actions/checkout@v2 18 | - name: Run tests 19 | run: cargo test --verbose 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.toptal.com/developers/gitignore/api/macos,rust,visualstudiocode 2 | 3 | ### macOS ### 4 | # General 5 | .DS_Store 6 | .AppleDouble 7 | .LSOverride 8 | 9 | # Icon must end with two \r 10 | Icon 11 | 12 | # Thumbnails 13 | ._* 14 | 15 | # Files that might appear in the root of a volume 16 | .DocumentRevisions-V100 17 | .fseventsd 18 | .Spotlight-V100 19 | .TemporaryItems 20 | .Trashes 21 | .VolumeIcon.icns 22 | .com.apple.timemachine.donotpresent 23 | 24 | # Directories potentially created on remote AFP share 25 | .AppleDB 26 | .AppleDesktop 27 | Network Trash Folder 28 | Temporary Items 29 | .apdisk 30 | 31 | ### VisualStudioCode ### 32 | .vscode/* 33 | !.vscode/settings.json 34 | !.vscode/tasks.json 35 | !.vscode/launch.json 36 | !.vscode/extensions.json 37 | *.code-workspace 38 | 39 | # Local History for Visual Studio Code 40 | .history/ 41 | 42 | ### VisualStudioCode Patch ### 43 | # Ignore all local history of files 44 | .history 45 | .ionide 46 | 47 | ### Rust ### 48 | # Generated by Cargo 49 | # will have compiled files and executables 50 | debug/ 51 | target/ 52 | 53 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 54 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 55 | Cargo.lock 56 | 57 | # These are backup files generated by rustfmt 58 | **/*.rs.bk 59 | 60 | # MSVC Windows builds of rustc generate these, which store debugging information 61 | *.pdb 62 | -------------------------------------------------------------------------------- /.rustfmt.toml: -------------------------------------------------------------------------------- 1 | max_width = 180 -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "leetcode-rust" 3 | version = "0.1.0" 4 | edition = "2018" 5 | 6 | [dependencies] 7 | automod = "1.0.2" 8 | regex = "1.5.4" 9 | walkdir = "2.3.2" -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2021 martinxxd 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/martwz/leetcode-rust/bd258c05e7eff54480e89598a912344687e635b0/logo.png -------------------------------------------------------------------------------- /src/binarysearch/minimum_bracket_addition.rs: -------------------------------------------------------------------------------- 1 | use std::collections::{HashMap, VecDeque}; 2 | 3 | /* 4 | Minimum Bracket Addition 5 | https://binarysearch.com/problems/Minimum-Bracket-Addition 6 | */ 7 | 8 | impl Solution { 9 | pub fn minimum_bracket_addition(s: String) -> i32 { 10 | let mut queue: VecDeque = VecDeque::new(); 11 | 12 | let mut inserts = 0; 13 | for c in s.chars() { 14 | if c == '(' { 15 | queue.push_back(c); 16 | } else if queue.back() == Some(&'(') { 17 | queue.pop_back(); 18 | } else { 19 | inserts += 1; 20 | } 21 | } 22 | 23 | inserts + queue.len() as i32 24 | } 25 | } 26 | 27 | struct Solution {} 28 | 29 | #[cfg(test)] 30 | mod tests { 31 | use super::*; 32 | 33 | #[test] 34 | fn test_minimum_bracket_addition() { 35 | assert_eq!(Solution::minimum_bracket_addition(")))((".to_string()), 5); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/binarysearch/mod.rs: -------------------------------------------------------------------------------- 1 | mod minimum_bracket_addition; 2 | -------------------------------------------------------------------------------- /src/leetcode/challenge/break_palindrome.rs: -------------------------------------------------------------------------------- 1 | // 1328. Break a Palindrome, Medium 2 | // https://leetcode.com/problems/break-a-palindrome/ 3 | impl Solution { 4 | pub fn break_palindrome(mut palindrome: String) -> String { 5 | let n = palindrome.len(); 6 | 7 | // can't break palindrom of length 1 8 | if palindrome.len() == 1 { 9 | return "".to_string(); 10 | } 11 | 12 | // is palindrom? 13 | for i in 0..n / 2 { 14 | if palindrome.chars().nth(i).unwrap() != palindrome.chars().nth(n - i - 1).unwrap() { 15 | return "".to_string(); 16 | } 17 | } 18 | 19 | // break palindrom 20 | let mut swapped = false; 21 | for i in 0..n { 22 | if palindrome.chars().nth(i).unwrap() != 'a' && !(n % 2 == 1 && i == n / 2) { 23 | palindrome.replace_range(i..i + 1, "a".to_string().as_str()); 24 | swapped = true; 25 | break; 26 | } 27 | } 28 | 29 | if !swapped { 30 | palindrome.replace_range(n - 1..n, "b".to_string().as_str()); 31 | } 32 | 33 | palindrome 34 | } 35 | } 36 | 37 | struct Solution {} 38 | 39 | #[cfg(test)] 40 | mod tests { 41 | use super::*; 42 | 43 | #[test] 44 | fn test_break_palindrome() { 45 | assert_eq!(Solution::break_palindrome("abccba".to_string()), "aaccba".to_string()); 46 | } 47 | 48 | #[test] 49 | fn test_break_palindrome2() { 50 | assert_eq!(Solution::break_palindrome("a".to_string()), "".to_string()); 51 | } 52 | 53 | #[test] 54 | fn test_break_palindrome3() { 55 | assert_eq!(Solution::break_palindrome("aa".to_string()), "ab".to_string()); 56 | } 57 | 58 | #[test] 59 | fn test_break_palindrome4() { 60 | assert_eq!(Solution::break_palindrome("aba".to_string()), "abb".to_string()); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/leetcode/challenge/calculate_minimum_hp.rs: -------------------------------------------------------------------------------- 1 | // 174. Dungeon Game, Hard 2 | // https://leetcode.com/problems/dungeon-game/ 3 | impl Solution { 4 | pub fn calculate_minimum_hp(dungeon: Vec>) -> i32 { 5 | let [n, m] = [dungeon.len(), dungeon[0].len()]; 6 | let mut dp = vec![vec![i32::max_value(); m + 1]; n + 1]; // (curr_health, min_health) 7 | 8 | dp[n - 1][m] = 1; 9 | dp[n][m - 1] = 1; 10 | 11 | for i in (0..n).rev() { 12 | for j in (0..m).rev() { 13 | dp[i][j] = i32::max(i32::min(dp[i + 1][j], dp[i][j + 1]) - dungeon[i][j], 1); 14 | } 15 | } 16 | 17 | dp[0][0] 18 | } 19 | } 20 | 21 | struct Solution {} 22 | 23 | #[cfg(test)] 24 | mod tests { 25 | use super::*; 26 | use crate::vec_vec_i32; 27 | 28 | #[test] 29 | fn test_calculate_minimum_hp() { 30 | assert_eq!(Solution::calculate_minimum_hp(vec_vec_i32![[-2, -3, 3], [-5, -10, 1], [10, 30, -5]]), 7); 31 | } 32 | 33 | #[test] 34 | fn test_calculate_minimum_hp2() { 35 | assert_eq!(Solution::calculate_minimum_hp(vec_vec_i32![[0]]), 1); 36 | } 37 | 38 | #[test] 39 | fn test_calculate_minimum_hp3() { 40 | assert_eq!(Solution::calculate_minimum_hp(vec_vec_i32![[100]]), 1); 41 | } 42 | 43 | #[test] 44 | fn test_calculate_minimum_hp4() { 45 | assert_eq!(Solution::calculate_minimum_hp(vec_vec_i32![[1, -3, 3], [0, -2, 0], [-3, -3, -3]]), 3); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/leetcode/challenge/can_partition_k_subsets.rs: -------------------------------------------------------------------------------- 1 | // 698. Partition to K Equal Sum Subsets, Medium 2 | // https://leetcode.com/problems/partition-to-k-equal-sum-subsets/ 3 | impl Solution { 4 | pub fn can_partition_k_subsets(mut nums: Vec, k: i32) -> bool { 5 | let sum = nums.iter().sum::(); 6 | if sum % k != 0 { 7 | return false; 8 | } 9 | let target = sum / k; 10 | 11 | nums.sort_unstable(); 12 | if nums[nums.len() - 1] > target { 13 | return false; 14 | } 15 | 16 | fn backtrack(nums: &Vec, target: i32, pos: usize, next: i32, used: &mut Vec) -> bool { 17 | if used.iter().all(|x| *x) { 18 | return true; 19 | } 20 | 21 | for i in pos..nums.len() { 22 | if used[i] || next + nums[i] > target { 23 | continue; 24 | } 25 | 26 | let next = (next + nums[i]) % target; 27 | used[i] = true; 28 | if backtrack(nums, target, if next == 0 { 0 } else { i + 1 }, next, used) { 29 | return true; 30 | } 31 | used[i] = false; 32 | } 33 | 34 | false 35 | } 36 | 37 | backtrack(&nums, target, 0, 0, &mut vec![false; nums.len()]) 38 | } 39 | } 40 | 41 | struct Solution {} 42 | 43 | #[cfg(test)] 44 | mod tests { 45 | use super::*; 46 | 47 | #[test] 48 | fn test_can_partition_k_subsets() { 49 | assert_eq!(Solution::can_partition_k_subsets(vec![4, 3, 2, 3, 5, 2, 1], 4), true); 50 | } 51 | 52 | #[test] 53 | fn test_can_partition_k_subsets2() { 54 | assert_eq!(Solution::can_partition_k_subsets(vec![1, 2, 3, 4], 3), false); 55 | } 56 | 57 | #[test] 58 | fn test_can_partition_k_subsets3() { 59 | assert_eq!(Solution::can_partition_k_subsets(vec![4, 3, 2, 3, 5, 2, 0], 4), false); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/leetcode/challenge/cherry_pickup.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | // 741. Cherry Pickup, Hard 4 | // https://leetcode.com/problems/cherry-pickup/ 5 | impl Solution { 6 | pub fn cherry_pickup(grid: Vec>) -> i32 { 7 | let n = grid.len(); 8 | 9 | let mut memo: HashMap<(usize, usize, usize, usize), i32> = HashMap::new(); 10 | 11 | fn dp(grid: &Vec>, n: &usize, i1: usize, j1: usize, i2: usize, j2: usize, memo: &mut HashMap<(usize, usize, usize, usize), i32>) -> i32 { 12 | if i1 >= *n || j1 >= *n || i2 >= *n || j2 >= *n { 13 | return -1; 14 | } else if i1 == *n - 1 && j1 == *n - 1 && i2 == *n - 1 && j2 == *n - 1 { 15 | return grid[i1][j1]; 16 | } else if grid[i1][j1] == -1 || grid[i2][j2] == -1 { 17 | return -1; 18 | } 19 | 20 | let key = &(i1, j1, i2, j2); 21 | if memo.contains_key(key) { 22 | return *memo.get(key).unwrap(); 23 | } 24 | 25 | let dd = dp(grid, n, i1 + 1, j1, i2 + 1, j2, memo); 26 | let dr = dp(grid, n, i1 + 1, j1, i2, j2 + 1, memo); 27 | let rd = dp(grid, n, i1, j1 + 1, i2 + 1, j2, memo); 28 | let rr = dp(grid, n, i1, j1 + 1, i2, j2 + 1, memo); 29 | 30 | let comb = i32::max(dd, i32::max(dr, i32::max(rd, rr))); 31 | 32 | let out; 33 | if comb == -1 { 34 | out = -1; 35 | } else if i1 == i2 && j1 == j2 { 36 | out = comb + grid[i1][j1]; 37 | } else { 38 | out = comb + grid[i1][j1] + grid[i2][j2]; 39 | } 40 | 41 | memo.insert(*key, out); 42 | out 43 | } 44 | 45 | i32::max(dp(&grid, &n, 0, 0, 0, 0, &mut memo), 0) 46 | } 47 | } 48 | 49 | struct Solution {} 50 | 51 | #[cfg(test)] 52 | mod tests { 53 | use super::*; 54 | use crate::vec_vec_i32; 55 | 56 | #[test] 57 | fn test_cherry_pickup() { 58 | assert_eq!(Solution::cherry_pickup(vec_vec_i32![[0, 1, -1], [1, 0, -1], [1, 1, 1]]), 5); 59 | } 60 | 61 | #[test] 62 | fn test_cherry_pickup2() { 63 | assert_eq!(Solution::cherry_pickup(vec_vec_i32![[1, 1, -1], [1, -1, 1], [-1, 1, 1]]), 0); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/leetcode/challenge/find_max_consecutive_ones.rs: -------------------------------------------------------------------------------- 1 | // 485. Max Consecutive Ones, Easy 2 | // https://leetcode.com/problems/max-consecutive-ones/ 3 | impl Solution { 4 | pub fn find_max_consecutive_ones(nums: Vec) -> i32 { 5 | let mut consecs = 0; 6 | let mut curr_consecs = 0; 7 | let mut prev: i32 = 1; 8 | for i in nums.iter() { 9 | if *i == 1 && prev == 1 { 10 | curr_consecs += 1; 11 | } else { 12 | prev = *i; 13 | curr_consecs = if *i == 1 { 1 } else { 0 }; 14 | } 15 | 16 | consecs = consecs.max(curr_consecs); 17 | } 18 | 19 | consecs 20 | } 21 | } 22 | 23 | struct Solution {} 24 | 25 | #[cfg(test)] 26 | mod tests { 27 | use super::*; 28 | use crate::vec_vec_i32; 29 | 30 | #[test] 31 | fn test_find_max_consecutive_ones() { 32 | assert_eq!(Solution::find_max_consecutive_ones(vec![1, 1, 0, 1, 1, 1]), 3); 33 | } 34 | 35 | #[test] 36 | fn test_find_max_consecutive_ones2() { 37 | assert_eq!(Solution::find_max_consecutive_ones(vec![1, 0, 1, 1, 0, 1]), 2); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/leetcode/challenge/intersect.rs: -------------------------------------------------------------------------------- 1 | use std::cmp::Ordering; 2 | use std::collections::HashMap; 3 | 4 | // 350. Intersection of Two Arrays II, Easy 5 | // https://leetcode.com/problems/intersection-of-two-arrays-ii/ 6 | impl Solution { 7 | pub fn intersect(nums1: Vec, nums2: Vec) -> Vec { 8 | let mut ans = vec![]; 9 | let mut map: HashMap = HashMap::new(); 10 | 11 | for num in nums1.iter() { 12 | *map.entry(*num).or_insert(0) += 1 13 | } 14 | 15 | for num in nums2.iter() { 16 | if *map.get(num).unwrap_or(&0) > 0 { 17 | *map.entry(*num).or_insert(0) -= 1; 18 | ans.push(*num); 19 | } 20 | } 21 | 22 | ans 23 | } 24 | 25 | pub fn intersect_using_pointers(mut nums1: Vec, mut nums2: Vec) -> Vec { 26 | let mut ans = vec![]; 27 | 28 | nums1.sort_unstable(); 29 | nums2.sort_unstable(); 30 | 31 | let [mut i, mut j, n, m] = [0, 0, nums1.len(), nums2.len()]; 32 | while i < n && j < m { 33 | match nums1[i].cmp(&nums2[j]) { 34 | Ordering::Less => i += 1, 35 | Ordering::Greater => j += 1, 36 | Ordering::Equal => { 37 | ans.push(nums1[i]); 38 | i += 1; 39 | j += 1; 40 | } 41 | } 42 | } 43 | 44 | ans 45 | } 46 | } 47 | 48 | struct Solution {} 49 | 50 | #[cfg(test)] 51 | mod tests { 52 | use super::*; 53 | 54 | #[test] 55 | fn test_intersect() { 56 | assert_eq!(Solution::intersect(vec![1, 2, 2, 1], vec![2, 2]), vec![2, 2]); 57 | } 58 | 59 | #[test] 60 | fn test_intersect2() { 61 | assert_eq!(Solution::intersect(vec![1, 2, 2, 1], vec![]), vec![]); 62 | } 63 | 64 | #[test] 65 | fn test_intersect3() { 66 | assert_eq!(Solution::intersect(vec![], vec![]), vec![]); 67 | } 68 | 69 | #[test] 70 | fn intersect_using_pointers() { 71 | assert_eq!(Solution::intersect_using_pointers(vec![1, 2, 2, 1], vec![2, 2]), vec![2, 2]); 72 | } 73 | 74 | #[test] 75 | fn intersect_using_pointers2() { 76 | assert_eq!(Solution::intersect_using_pointers(vec![1, 2, 2, 1], vec![]), vec![]); 77 | } 78 | 79 | #[test] 80 | fn intersect_using_pointers3() { 81 | assert_eq!(Solution::intersect_using_pointers(vec![], vec![]), vec![]); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/leetcode/challenge/is_valid_palindrome.rs: -------------------------------------------------------------------------------- 1 | // 1216. Valid Palindrome III, Hard 2 | // https://leetcode.com/problems/valid-palindrome-iii/ 3 | impl Solution { 4 | pub fn is_valid_palindrome(s: String, k: i32) -> bool { 5 | let n = s.len(); 6 | let mut dp = vec![vec![0; n]; n]; 7 | 8 | let chars = s.chars().collect::>(); 9 | 10 | for i in 0..n { 11 | dp[i][i] = 1; 12 | } 13 | 14 | for i in 1..n { 15 | for j in 0..n - i { 16 | let i = j + i; 17 | if chars[j] == chars[i] { 18 | dp[j][i] = 2 + dp[j + 1][i - 1]; 19 | } else { 20 | dp[j][i] = i32::max(dp[j + 1][i], dp[j][i - 1]); 21 | } 22 | } 23 | } 24 | 25 | dp[0][n - 1] >= n as i32 - k 26 | } 27 | } 28 | 29 | struct Solution {} 30 | 31 | #[cfg(test)] 32 | mod tests { 33 | use super::*; 34 | use crate::{vec_vec_char, vec_vec_i32}; 35 | 36 | #[test] 37 | fn test_is_valid_palindrome() { 38 | assert_eq!(Solution::is_valid_palindrome("abcdeca".to_string(), 2), true); 39 | } 40 | 41 | #[test] 42 | fn test_is_valid_palindrome2() { 43 | assert_eq!(Solution::is_valid_palindrome("abbababa".to_string(), 1), true); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/leetcode/challenge/longest_common_subsequence.rs: -------------------------------------------------------------------------------- 1 | // 1143. Longest Common Subsequence, Medium 2 | // https://leetcode.com/problems/longest-common-subsequence/ 3 | impl Solution { 4 | pub fn longest_common_subsequence(text1: String, text2: String) -> i32 { 5 | let [n, m] = [text1.len(), text2.len()]; 6 | let mut dp = vec![vec![0; n + 1]; m + 1]; 7 | 8 | for i in 0..n { 9 | for j in 0..m { 10 | if text1.chars().nth(i).unwrap() == text2.chars().nth(j).unwrap() { 11 | dp[j + 1][i + 1] = dp[j][i] + 1; 12 | } else { 13 | dp[j + 1][i + 1] = dp[j + 1][i].max(dp[j][i + 1]); 14 | } 15 | } 16 | } 17 | 18 | *dp.last().unwrap().last().unwrap() 19 | } 20 | } 21 | 22 | struct Solution {} 23 | 24 | #[cfg(test)] 25 | mod tests { 26 | use super::*; 27 | 28 | #[test] 29 | fn test_longest_common_subsequence() { 30 | assert_eq!(Solution::longest_common_subsequence("abcde".to_string(), "ace".to_string()), 3); 31 | } 32 | 33 | #[test] 34 | fn test_longest_common_subsequence2() { 35 | assert_eq!(Solution::longest_common_subsequence("abc".to_string(), "abc".to_string()), 3); 36 | } 37 | 38 | #[test] 39 | fn test_longest_common_subsequence3() { 40 | assert_eq!(Solution::longest_common_subsequence("abc".to_string(), "def".to_string()), 0); 41 | } 42 | 43 | #[test] 44 | fn test_longest_common_subsequence4() { 45 | assert_eq!(Solution::longest_common_subsequence("abc".to_string(), "".to_string()), 0); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/leetcode/challenge/max_length.rs: -------------------------------------------------------------------------------- 1 | // 1239. Maximum Length of a Concatenated String with Unique Characters, Medium 2 | // https://leetcode.com/problems/maximum-length-of-a-concatenated-string-with-unique-characters/ 3 | impl Solution { 4 | pub fn max_length(arr: Vec) -> i32 { 5 | let mut dp = vec![[0; 26]]; 6 | 7 | 'outer: for str in arr.iter() { 8 | let mut bitmap = [0; 26]; 9 | for ch in str.chars() { 10 | let i = ch as usize - 'a' as usize; 11 | bitmap[i] += 1; 12 | if bitmap[i] > 1 { 13 | continue 'outer; 14 | } 15 | } 16 | 17 | let tmp_dp = dp.clone(); 18 | 'inner: for str_dp in tmp_dp.iter() { 19 | let mut tmp_bitmap = bitmap; 20 | for i in 0..26 { 21 | tmp_bitmap[i] += str_dp[i]; 22 | if tmp_bitmap[i] > 1 { 23 | continue 'inner; 24 | } 25 | } 26 | 27 | dp.push(tmp_bitmap); 28 | } 29 | } 30 | 31 | dp.iter().map(|x| x.iter().sum::()).max().unwrap() 32 | } 33 | } 34 | 35 | struct Solution {} 36 | 37 | #[cfg(test)] 38 | mod tests { 39 | use super::*; 40 | 41 | #[test] 42 | fn test_max_length() { 43 | assert_eq!(Solution::max_length(vec!["un".to_string(), "iq".to_string(), "ue".to_string()]), 4); 44 | } 45 | 46 | #[test] 47 | fn test_max_length2() { 48 | assert_eq!(Solution::max_length(vec!["cha".to_string(), "r".to_string(), "act".to_string(), "ers".to_string()]), 6); 49 | } 50 | 51 | #[test] 52 | fn test_max_length3() { 53 | assert_eq!(Solution::max_length(vec!["abcdefghijklmnopqrstuvwxyz".to_string()]), 26); 54 | } 55 | 56 | #[test] 57 | fn test_max_length4() { 58 | assert_eq!(Solution::max_length(vec!["yy".to_string(), "bkhwmpbiisbldzknpm".to_string()]), 0); 59 | } 60 | 61 | #[test] 62 | fn test_max_length5() { 63 | assert_eq!( 64 | Solution::max_length(vec!["a".to_string(), "abc".to_string(), "d".to_string(), "de".to_string(), "def".to_string()]), 65 | 6 66 | ); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/leetcode/challenge/max_sub_array_len.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | // 325. Maximum Size Subarray Sum Equals k, Medium 4 | // https://leetcode.com/problems/maximum-size-subarray-sum-equals-k/solution/ 5 | impl Solution { 6 | pub fn max_sub_array_len(nums: Vec, k: i32) -> i32 { 7 | let mut max_length = 0; 8 | 9 | let mut curr_sum = 0; 10 | let mut sum_to_index_mapping = HashMap::new(); 11 | for i in 0..nums.len() { 12 | curr_sum += nums[i]; 13 | 14 | if curr_sum == k { 15 | max_length = max_length.max(i + 1); 16 | } else if let Some(j) = sum_to_index_mapping.get(&(curr_sum - k)) { 17 | max_length = max_length.max(i - j); 18 | } 19 | 20 | sum_to_index_mapping.entry(curr_sum).or_insert(i); 21 | } 22 | 23 | max_length as i32 24 | } 25 | } 26 | 27 | struct Solution {} 28 | 29 | #[cfg(test)] 30 | mod tests { 31 | use super::*; 32 | 33 | #[test] 34 | fn test_max_sub_array_len() { 35 | assert_eq!(Solution::max_sub_array_len(vec![1, -1, 5, -2, 3], 3), 4); 36 | } 37 | 38 | #[test] 39 | fn test_max_sub_array_len2() { 40 | assert_eq!(Solution::max_sub_array_len(vec![-2, -1, 2, 1], 1), 2); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/leetcode/challenge/minmax_gas_dist.rs: -------------------------------------------------------------------------------- 1 | // 774. Minimize Max Distance to Gas Station, Medium 2 | // https://leetcode.com/problems/minimize-max-distance-to-gas-station/ 3 | impl Solution { 4 | pub fn minmax_gas_dist(stations: Vec, k: i32) -> f64 { 5 | fn is_valid(stations: &Vec, k: i32, mid: f64) -> bool { 6 | let mut count = 0; 7 | 8 | (1..stations.len()).for_each(|i| { 9 | count += ((stations[i] - stations[i - 1]) as f64 / mid) as i32; 10 | }); 11 | 12 | count <= k 13 | } 14 | 15 | let [mut l, mut r] = [0.0, 1e8]; 16 | while r - l > 1e-6 { 17 | let mid = (l + r) / 2.0; 18 | if is_valid(&stations, k, mid) { 19 | r = mid; 20 | } else { 21 | l = mid; 22 | } 23 | } 24 | 25 | l 26 | } 27 | } 28 | 29 | struct Solution {} 30 | 31 | #[cfg(test)] 32 | mod tests { 33 | use super::*; 34 | 35 | #[test] 36 | fn test_minmax_gas_dist() { 37 | assert!(0.4 < Solution::minmax_gas_dist(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 9) && Solution::minmax_gas_dist(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 9) < 0.6,); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/leetcode/challenge/mod.rs: -------------------------------------------------------------------------------- 1 | automod::dir!("src/leetcode/challenge"); 2 | -------------------------------------------------------------------------------- /src/leetcode/challenge/moves_to_chessboard.rs: -------------------------------------------------------------------------------- 1 | impl Solution { 2 | pub fn moves_to_chessboard(board: Vec>) -> i32 { 3 | let n = board.len(); 4 | 5 | for i in 0..n { 6 | for j in 0..n { 7 | if board[0][0] ^ board[i][0] ^ board[0][j] ^ board[i][j] == 1 { 8 | return -1; 9 | } 10 | } 11 | } 12 | 13 | let [mut row_sum, mut col_sum, mut row_misplaced, mut col_misplaced] = [0, 0, 0, 0]; 14 | for i in 0..n { 15 | row_sum += board[0][i]; 16 | col_sum += board[i][0]; 17 | 18 | if board[i][0] == i as i32 % 2 { 19 | row_misplaced += 1; 20 | } 21 | if board[0][i] == i as i32 % 2 { 22 | col_misplaced += 1; 23 | } 24 | } 25 | 26 | let n = n as i32; 27 | if row_sum != n / 2 && row_sum != (n + 1) / 2 { 28 | return -1; 29 | } 30 | if col_sum != n / 2 && col_sum != (n + 1) / 2 { 31 | return -1; 32 | } 33 | 34 | if n % 2 == 1 { 35 | if col_misplaced % 2 == 1 { 36 | col_misplaced = n - col_misplaced; 37 | } 38 | if row_misplaced % 2 == 1 { 39 | row_misplaced = n - row_misplaced; 40 | } 41 | } else { 42 | col_misplaced = i32::min(n - col_misplaced, col_misplaced); 43 | row_misplaced = i32::min(n - row_misplaced, row_misplaced); 44 | } 45 | 46 | (col_misplaced + row_misplaced) / 2 47 | } 48 | } 49 | 50 | struct Solution {} 51 | 52 | #[cfg(test)] 53 | mod tests { 54 | use super::*; 55 | use crate::vec_vec_i32; 56 | 57 | #[test] 58 | fn test_moves_to_chessboard() { 59 | assert_eq!(Solution::moves_to_chessboard(vec_vec_i32![[0, 1, 1, 0], [0, 1, 1, 0], [1, 0, 0, 1], [1, 0, 0, 1]]), 2); 60 | } 61 | 62 | #[test] 63 | fn test_moves_to_chessboard2() { 64 | assert_eq!(Solution::moves_to_chessboard(vec_vec_i32![[0, 1], [1, 0]]), 0); 65 | } 66 | 67 | #[test] 68 | fn test_moves_to_chessboard3() { 69 | assert_eq!(Solution::moves_to_chessboard(vec_vec_i32![[1, 0], [1, 0]]), -1); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/leetcode/challenge/num_distinct.rs: -------------------------------------------------------------------------------- 1 | // 115. Distinct Subsequences, Hard 2 | // https://leetcode.com/problems/distinct-subsequences/ 3 | impl Solution { 4 | pub fn num_distinct(s: String, t: String) -> i32 { 5 | let [m, n] = [s.len(), t.len()]; 6 | let mut dp = vec![vec![0; n + 1]; m + 1]; 7 | 8 | for i in 0..m { 9 | dp[i][0] = 1; 10 | } 11 | 12 | for i in 1..m+1 { 13 | for j in 1..n+1 { 14 | if s.chars().nth(i - 1) == t.chars().nth(j - 1) { 15 | dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j]; 16 | } else { 17 | dp[i][j] = dp[i - 1][j]; 18 | } 19 | } 20 | } 21 | 22 | dp[m][n] 23 | } 24 | } 25 | 26 | struct Solution {} 27 | 28 | #[cfg(test)] 29 | mod tests { 30 | use super::*; 31 | 32 | #[test] 33 | fn test_num_distinct() { 34 | assert_eq!(Solution::num_distinct("rabbbit".to_string(), "rabbit".to_string()), 3); 35 | } 36 | 37 | #[test] 38 | fn test_num_distinct2() { 39 | assert_eq!(Solution::num_distinct("babgbag".to_string(), "bag".to_string()), 5); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/leetcode/challenge/num_unique_emails.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashSet; 2 | 3 | // 929. Unique Email Addresses, Easy 4 | // https://leetcode.com/problems/unique-email-addresses/ 5 | impl Solution { 6 | pub fn num_unique_emails(emails: Vec) -> i32 { 7 | let mut set = HashSet::new(); 8 | 9 | for email in emails { 10 | let email: Vec<_> = email.split('@').collect(); 11 | let mut vhost: String = email[0].to_string().replace(".", ""); 12 | if vhost.contains('+') { 13 | vhost = vhost.split('+').next().unwrap().to_string(); 14 | } 15 | 16 | let domain: String = email[1].to_string(); 17 | 18 | set.insert(format!("{}@{}", vhost, domain)); 19 | } 20 | 21 | set.len() as i32 22 | } 23 | } 24 | 25 | struct Solution {} 26 | 27 | #[cfg(test)] 28 | mod tests { 29 | use super::*; 30 | use crate::vec_string; 31 | 32 | #[test] 33 | fn test_num_unique_emails() { 34 | assert_eq!( 35 | Solution::num_unique_emails(vec_string![ 36 | "test.email+alex@leetcode.com", 37 | "test.e.mail+bob.cathy@leetcode.com", 38 | "testemail+david@lee.tcode.com" 39 | ]), 40 | 2 41 | ); 42 | } 43 | 44 | #[test] 45 | fn test_num_unique_emails2() { 46 | assert_eq!(Solution::num_unique_emails(vec_string!["a@leetcode.com", "b@leetcode.com", "c@leetcode.com"]), 3); 47 | } 48 | 49 | #[test] 50 | fn test_num_unique_emails3() { 51 | assert_eq!(Solution::num_unique_emails(vec_string!["a@leetcode.com", "a@leetcode.com"]), 1); 52 | } 53 | 54 | #[test] 55 | fn test_num_unique_emails4() { 56 | assert_eq!(Solution::num_unique_emails(vec_string![]), 0); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/leetcode/challenge/shortest_distance.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | use std::collections::VecDeque; 3 | 4 | // 317. Shortest Distance from All Buildings, Hard 5 | // https://leetcode.com/problems/shortest-distance-from-all-buildings/ 6 | impl Solution { 7 | pub fn shortest_distance(grid: Vec>) -> i32 { 8 | fn manhattan_distance(x0: i32, x1: i32, y0: i32, y1: i32) -> i32 { 9 | i32::abs(x0 - x1) + i32::abs(y0 - y1) 10 | } 11 | 12 | fn dfs(grid: &Vec>, x: i32, y: i32) -> Vec<(i32, i32)> { 13 | let mut dists: Vec<(i32, i32)> = vec![]; 14 | 15 | let directions: Vec<(i32, i32)> = vec![(1, 0), (-1, 0), (0, 1), (0, -1)]; 16 | let mut queue: VecDeque<(i32, i32)> = VecDeque::new(); 17 | let mut seen: Vec<(i32, i32)> = Vec::new(); 18 | 19 | queue.push_back((x, y)); 20 | 21 | while !queue.is_empty() { 22 | let (x, y) = queue.pop_front().unwrap(); 23 | 24 | if x < 0 || x >= grid.len() as i32 || y < 0 || y >= grid[0].len() as i32 { 25 | continue; 26 | } else if seen.contains(&(x, y)) { 27 | continue; 28 | } else if grid[x as usize][y as usize] == 2 { 29 | continue; 30 | } else if grid[x as usize][y as usize] == 1 { 31 | dists.push((x, y)); 32 | seen.push((x, y)); 33 | continue; 34 | } 35 | 36 | seen.push((x, y)); 37 | 38 | for (dx, dy) in directions.iter() { 39 | let nx = x + dx; 40 | let ny = y + dy; 41 | 42 | queue.push_back((nx, ny)); 43 | } 44 | } 45 | 46 | dists 47 | } 48 | 49 | let rows = grid.len(); 50 | if rows == 0 { 51 | return -1; 52 | } 53 | let cols = grid[0].len(); 54 | 55 | let mut dist_map: HashMap = HashMap::new(); 56 | let mut friends = 0; 57 | for r in 0..rows { 58 | for c in 0..cols { 59 | if grid[r][c] == 1 { 60 | friends += 1; 61 | } 62 | if grid[r][c] == 0 { 63 | let dists = dfs(&grid, r as i32, c as i32); 64 | let mut curr_dist = 0; 65 | for dist in dists.iter() { 66 | curr_dist += manhattan_distance(r as i32, dist.0, c as i32, dist.1); 67 | } 68 | println!("{:?}", curr_dist); 69 | dist_map.insert(dists.len() as i32, curr_dist.min(*dist_map.get(&(dists.len() as i32)).unwrap_or(&std::i32::MAX))); 70 | } 71 | } 72 | } 73 | 74 | println!("{:?}", dist_map); 75 | 76 | *dist_map.get(&friends).unwrap_or(&-1) 77 | } 78 | } 79 | 80 | struct Solution {} 81 | 82 | #[cfg(test)] 83 | mod tests { 84 | use crate::vec_vec_i32; 85 | 86 | use super::*; 87 | 88 | #[test] 89 | fn test_shortest_distance() { 90 | assert_eq!(Solution::shortest_distance(vec_vec_i32![[1, 0, 2, 0, 1], [0, 0, 0, 0, 0], [0, 0, 1, 0, 0]]), 7); 91 | } 92 | 93 | #[test] 94 | fn test_shortest_distance2() { 95 | assert_eq!(Solution::shortest_distance(vec_vec_i32![[1, 0]]), 1); 96 | } 97 | 98 | #[test] 99 | fn test_shortest_distance3() { 100 | assert_eq!(Solution::shortest_distance(vec_vec_i32![[1]]), -1); 101 | } 102 | 103 | #[test] 104 | fn test_shortest_distance4() { 105 | assert_eq!(Solution::shortest_distance(vec_vec_i32![[1, 2, 0]]), -1); 106 | } 107 | 108 | #[test] 109 | fn test_shortest_distance5() { 110 | assert_eq!(Solution::shortest_distance(vec_vec_i32![[0, 2, 1], [1, 0, 2], [0, 1, 0]]), -1); 111 | } 112 | 113 | #[test] 114 | fn test_shortest_distance6() { 115 | assert_eq!(Solution::shortest_distance(vec_vec_i32![[1, 1], [0, 1]]), -1); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/leetcode/challenge/shortest_path.rs: -------------------------------------------------------------------------------- 1 | use std::collections::{HashSet}; 2 | use std::iter::FromIterator; 3 | 4 | // 1293. Shortest Path in a Grid with Obstacles Elimination, Hard 5 | // https://leetcode.com/problems/shortest-path-in-a-grid-with-obstacles-elimination/ 6 | impl Solution { 7 | pub fn shortest_path(grid: Vec>, k: i32) -> i32 { 8 | fn bfs(grid: &Vec>, pos: (i32, i32), obstacles_left: i32, mut visited: HashSet<(i32, i32)>, paths: &mut Vec>) { 9 | let n = grid.len(); 10 | if n == 0 { 11 | return; 12 | } 13 | let m = grid[0].len(); 14 | 15 | // reached end? 16 | if pos.0 == n as i32 - 1 && pos.1 == m as i32 - 1 { 17 | paths.push(Vec::from_iter(visited)); 18 | return; 19 | } 20 | 21 | visited.insert((pos.0, pos.1)); 22 | 23 | let directions = vec![(0, 1), (0, -1), (1, 0), (-1, 0)]; 24 | for direction in directions { 25 | let next_pos = (pos.0 + direction.0, pos.1 + direction.1); 26 | let new_visited = visited.clone(); 27 | // in bounds? 28 | if next_pos.0 < 0 || next_pos.0 >= n as i32 || next_pos.1 < 0 || next_pos.1 >= m as i32 { 29 | continue; 30 | } 31 | // not visited? 32 | if new_visited.contains(&(next_pos.0, next_pos.1)) { 33 | continue; 34 | } 35 | 36 | if grid[next_pos.0 as usize][next_pos.1 as usize] == 1 && obstacles_left > 0 { 37 | bfs(grid, next_pos, obstacles_left - 1, new_visited, paths); 38 | } else if grid[next_pos.0 as usize][next_pos.1 as usize] == 0 { 39 | bfs(grid, next_pos, obstacles_left, new_visited, paths); 40 | } 41 | } 42 | } 43 | 44 | let mut paths = Vec::new(); 45 | 46 | // start is obstacle? 47 | if !grid.is_empty() && !grid[0].is_empty() && grid[0][0] == 1 { 48 | return -1; 49 | } 50 | bfs(&grid, (0, 0), k, HashSet::new(), &mut paths); 51 | 52 | paths.sort_by_key(|a| a.len()); 53 | if let Some(path) = paths.first() { 54 | path.len() as i32 55 | } else { 56 | -1 57 | } 58 | } 59 | } 60 | 61 | struct Solution {} 62 | 63 | #[cfg(test)] 64 | mod tests { 65 | use super::*; 66 | use crate::vec_vec_i32; 67 | 68 | #[test] 69 | fn test_shortest_path() { 70 | assert_eq!(Solution::shortest_path(vec_vec_i32![[0, 0, 0], [1, 1, 0], [0, 0, 0], [0, 1, 1], [0, 0, 0]], 1), 6); 71 | } 72 | 73 | #[test] 74 | fn test_shortest_path2() { 75 | assert_eq!(Solution::shortest_path(vec_vec_i32![[0, 1, 1], [1, 1, 1], [1, 0, 0]], 1), -1); 76 | } 77 | 78 | #[test] 79 | fn test_shortest_path3() { 80 | assert_eq!(Solution::shortest_path(vec_vec_i32![[]], 0), -1); 81 | } 82 | 83 | #[test] 84 | fn test_shortest_path4() { 85 | assert_eq!(Solution::shortest_path(vec_vec_i32![[1]], 0), -1); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/leetcode/challenge/sort_array_by_parity_ii.rs: -------------------------------------------------------------------------------- 1 | use std::collections::VecDeque; 2 | 3 | // 922. Sort Array By Parity II, Easy 4 | // https://leetcode.com/problems/sort-array-by-parity-ii/ 5 | impl Solution { 6 | pub fn sort_array_by_parity_ii(nums: Vec) -> Vec { 7 | let n = nums.len(); 8 | let mut ans: Vec = Vec::new(); 9 | 10 | let mut p1: VecDeque = VecDeque::new(); 11 | let mut p2: VecDeque = VecDeque::new(); 12 | 13 | for num in nums { 14 | if num % 2 == 0 { 15 | p1.push_back(num); 16 | } else { 17 | p2.push_back(num); 18 | } 19 | } 20 | 21 | for i in 0..n { 22 | if i % 2 == 0 { 23 | ans.push(p1.pop_front().unwrap()); 24 | } else { 25 | ans.push(p2.pop_front().unwrap()); 26 | } 27 | } 28 | 29 | ans 30 | } 31 | } 32 | 33 | struct Solution {} 34 | 35 | #[cfg(test)] 36 | mod tests { 37 | use super::*; 38 | 39 | #[test] 40 | fn test_sort_array_by_parity_ii() { 41 | assert_eq!(Solution::sort_array_by_parity_ii(vec![4, 2, 5, 7]).len(), 4); 42 | } 43 | 44 | #[test] 45 | fn test_sort_array_by_parity_ii2() { 46 | assert_eq!(Solution::sort_array_by_parity_ii(vec![2, 3]), vec![2, 3]); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/leetcode/challenge/spiral_order.rs: -------------------------------------------------------------------------------- 1 | // 54. Spiral Matrix, Medium 2 | // https://leetcode.com/problems/spiral-matrix/ 3 | impl Solution { 4 | pub fn spiral_order(matrix: Vec>) -> Vec { 5 | let mut ans = vec![]; 6 | // edge cases: 7 | if matrix.is_empty() || matrix[0].is_empty() { 8 | return ans; 9 | } else if matrix[0].len() == 1 { 10 | matrix.iter().flatten().for_each(|f| { 11 | ans.push(*f); 12 | }); 13 | return ans; 14 | } 15 | 16 | let [mut n, mut m] = [matrix.len() - 1, matrix[0].len() - 1]; 17 | let cells = (n + 1) * (m + 1); 18 | let mut i = 0; 19 | 20 | #[derive(PartialEq)] 21 | enum Direction { 22 | RIGHT, 23 | DOWN, 24 | LEFT, 25 | UP, 26 | } 27 | 28 | let mut direction = Direction::RIGHT; 29 | let mut pos = (0, 0); 30 | ans.push(matrix[pos.0][pos.1]); 31 | 32 | while i < cells - 1 { 33 | if m > 0 && direction == Direction::RIGHT { 34 | for _j in 0..m { 35 | pos = (pos.0, pos.1 + 1); 36 | ans.push(matrix[pos.0][pos.1]); 37 | } 38 | if i != 0 { 39 | m -= 1; 40 | } 41 | direction = Direction::DOWN; 42 | } else if n > 0 && direction == Direction::DOWN { 43 | for _j in 0..n { 44 | pos = (pos.0 + 1, pos.1); 45 | ans.push(matrix[pos.0][pos.1]); 46 | } 47 | n -= 1; 48 | direction = Direction::LEFT; 49 | } else if m > 0 && direction == Direction::LEFT { 50 | for _j in 0..m { 51 | pos = (pos.0, pos.1 - 1); 52 | ans.push(matrix[pos.0][pos.1]); 53 | } 54 | m -= 1; 55 | direction = Direction::UP; 56 | } else if n > 0 && direction == Direction::UP { 57 | for _j in 0..n { 58 | pos = (pos.0 - 1, pos.1); 59 | ans.push(matrix[pos.0][pos.1]); 60 | } 61 | n -= 1; 62 | direction = Direction::RIGHT; 63 | } 64 | 65 | i += 1; 66 | } 67 | 68 | ans 69 | } 70 | } 71 | 72 | struct Solution {} 73 | 74 | #[cfg(test)] 75 | mod tests { 76 | use super::*; 77 | 78 | #[test] 79 | fn test_spiral_order() { 80 | assert_eq!(Solution::spiral_order(vec![vec![1, 2, 3], vec![4, 5, 6], vec![7, 8, 9]]), vec![1, 2, 3, 6, 9, 8, 7, 4, 5]); 81 | } 82 | 83 | #[test] 84 | fn test_spiral_order2() { 85 | assert_eq!( 86 | Solution::spiral_order(vec![vec![1, 2, 3, 4], vec![5, 6, 7, 8], vec![9, 10, 11, 12]]), 87 | vec![1, 2, 3, 4, 8, 12, 11, 10, 9, 5, 6, 7] 88 | ); 89 | } 90 | 91 | #[test] 92 | fn test_spiral_order3() { 93 | assert_eq!(Solution::spiral_order(vec![vec![1]]), vec![1]); 94 | } 95 | 96 | #[test] 97 | fn test_spiral_order4() { 98 | assert_eq!(Solution::spiral_order(vec![vec![3], vec![2]]), vec![3, 2]); 99 | } 100 | 101 | #[test] 102 | fn test_spiral_order5() { 103 | assert_eq!(Solution::spiral_order(vec![vec![3, 2], vec![0, 1]]), vec![3, 2, 1, 0]); 104 | } 105 | 106 | #[test] 107 | fn test_spiral_order6() { 108 | assert_eq!(Solution::spiral_order(vec![]), vec![]); 109 | } 110 | 111 | #[test] 112 | fn test_spiral_order7() { 113 | assert_eq!( 114 | Solution::spiral_order(vec![vec![1, 2, 3, 4], vec![5, 6, 7, 8], vec![9, 10, 11, 12], vec![13, 14, 15, 16]]), 115 | vec![1, 2, 3, 4, 8, 12, 16, 15, 14, 13, 9, 5, 6, 7, 11, 10] 116 | ); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/leetcode/challenge/split_list_to_parts.rs: -------------------------------------------------------------------------------- 1 | // Definition for singly-linked list. 2 | #[derive(PartialEq, Eq, Clone, Debug)] 3 | pub struct ListNode { 4 | pub val: i32, 5 | pub next: Option>, 6 | } 7 | 8 | impl ListNode { 9 | #[inline] 10 | fn new(val: i32) -> Self { 11 | ListNode { next: None, val } 12 | } 13 | } 14 | 15 | // 725. Split Linked List in Parts, Medium 16 | // https://leetcode.com/problems/split-linked-list-in-parts/ 17 | impl Solution { 18 | pub fn split_list_to_parts(head: Option>, k: i32) -> Vec>> { 19 | let mut len = 0; 20 | let mut node = &head; 21 | 22 | while let Some(n) = node { 23 | len += 1; 24 | node = &n.next; 25 | } 26 | 27 | let mut head = head; 28 | let mut answer = Vec::with_capacity(k as usize); 29 | 30 | for i in 0..k as usize { 31 | answer.push(head); 32 | let mut node = &mut answer[i]; 33 | for _ in 0..len / k + if i < (len % k) as usize { 1 } else { 0 } { 34 | if let Some(n) = node { 35 | node = &mut n.next; 36 | } 37 | } 38 | head = node.take(); 39 | } 40 | answer 41 | } 42 | } 43 | 44 | struct Solution {} 45 | -------------------------------------------------------------------------------- /src/leetcode/challenge/tictactoe.rs: -------------------------------------------------------------------------------- 1 | // 1275. Find Winner on a Tic Tac Toe Game, Easy 2 | // https://leetcode.com/problems/find-winner-on-a-tic-tac-toe-game/ 3 | impl Solution { 4 | pub fn tictactoe(moves: Vec>) -> String { 5 | let mut board = vec![vec![-1; 3]; 3]; 6 | 7 | let mut player: i8 = 0; 8 | for m in moves.iter() { 9 | board[m[0] as usize][m[1] as usize] = player; 10 | 11 | // check for win 12 | for i in 0..3 { 13 | let mut row = vec![]; 14 | let mut col = vec![]; 15 | for j in 0..3 { 16 | if board[i][j] == player { 17 | row.push(board[i][j]); 18 | } 19 | if board[j][i] == player { 20 | col.push(board[j][i]); 21 | } 22 | } 23 | if row.len() == 3 || col.len() == 3 { 24 | if player == 0 { 25 | return "A".to_string(); 26 | } else { 27 | return "B".to_string(); 28 | } 29 | } 30 | // diagonal 31 | if player == board[1][1] && player == board[2][2] && player == board[0][0] { 32 | if player == 0 { 33 | return "A".to_string(); 34 | } else { 35 | return "B".to_string(); 36 | } 37 | } 38 | if player == board[1][1] && player == board[0][2] && player == board[2][0] { 39 | if player == 0 { 40 | return "A".to_string(); 41 | } else { 42 | return "B".to_string(); 43 | } 44 | } 45 | } 46 | 47 | player ^= 1; 48 | } 49 | 50 | if moves.len() == 9 { 51 | "Draw".to_string() 52 | } else { 53 | "Pending".to_string() 54 | } 55 | } 56 | } 57 | 58 | struct Solution {} 59 | 60 | #[cfg(test)] 61 | mod tests { 62 | use super::*; 63 | use crate::vec_vec_i32; 64 | 65 | #[test] 66 | fn test_tictactoe() { 67 | assert_eq!(Solution::tictactoe(vec_vec_i32![[0, 0], [2, 0], [1, 1], [2, 1], [2, 2]]), "A"); 68 | } 69 | 70 | #[test] 71 | fn test_tictactoe2() { 72 | assert_eq!(Solution::tictactoe(vec_vec_i32![[0, 0], [1, 1], [0, 1], [0, 2], [1, 0], [2, 0]]), "B"); 73 | } 74 | 75 | #[test] 76 | fn test_tictactoe3() { 77 | assert_eq!( 78 | Solution::tictactoe(vec_vec_i32![[0, 0], [1, 1], [2, 0], [1, 0], [1, 2], [2, 1], [0, 1], [0, 2], [2, 2]]), 79 | "Draw" 80 | ); 81 | } 82 | 83 | #[test] 84 | fn test_tictactoe4() { 85 | assert_eq!(Solution::tictactoe(vec_vec_i32![[0, 0], [1, 1]]), "Pending"); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/leetcode/challenge/tribonacci.rs: -------------------------------------------------------------------------------- 1 | // 1137. N-th Tribonacci Number, Easy 2 | // https://leetcode.com/problems/n-th-tribonacci-number/ 3 | impl Solution { 4 | pub fn tribonacci(n: i32) -> i32 { 5 | let mut cache = vec![0; n as usize + 1]; 6 | for i in 0..n + 1 { 7 | if i == 0 { 8 | cache[0] = 0; 9 | } else if i == 1 { 10 | cache[1] = 1; 11 | } else if i == 2 { 12 | cache[2] = 1; 13 | } else { 14 | cache[i as usize] = cache[i as usize - 3] + cache[i as usize - 2] + cache[i as usize - 1]; 15 | } 16 | } 17 | println!("{:?}", cache); 18 | cache[n as usize] 19 | } 20 | } 21 | struct Solution {} 22 | 23 | #[cfg(test)] 24 | mod tests { 25 | use super::*; 26 | use crate::vec_vec_i32; 27 | 28 | #[test] 29 | fn test_tribonacci() { 30 | assert_eq!(Solution::tribonacci(4), 4); 31 | } 32 | 33 | #[test] 34 | fn test_tribonacci2() { 35 | assert_eq!(Solution::tribonacci(25), 1389537); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/leetcode/contest/mod.rs: -------------------------------------------------------------------------------- 1 | mod biweekly_62; 2 | mod biweekly_63; 3 | mod weekly_261; 4 | mod weekly_262; 5 | mod weekly_263; 6 | -------------------------------------------------------------------------------- /src/leetcode/contest/weekly_261.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | // 2027. Minimum Moves to Convert String, Easy 4 | // https://leetcode.com/problems/minimum-moves-to-convert-string/ 5 | impl Solution1 { 6 | pub fn minimum_moves(s: String) -> i32 { 7 | let mut arr: Vec = vec![]; 8 | 9 | for ch in s.chars() { 10 | if ch == 'X' { 11 | arr.push(1); 12 | } else { 13 | arr.push(0); 14 | } 15 | } 16 | 17 | let mut moves = 0; 18 | let n = arr.len(); 19 | let [mut l, mut r] = [0, 0]; 20 | while r < n { 21 | if r - l < 2 { 22 | r += 1; 23 | } else if arr[l] == 1 { 24 | arr[l] = 0; 25 | arr[l + 1] = 0; 26 | arr[l + 2] = 0; 27 | moves += 1; 28 | } else { 29 | l += 1; 30 | } 31 | 32 | if r == n && (arr[r - 1] == 1 || arr[r - 2] == 1 || arr[r - 3] == 1) { 33 | moves += 1; 34 | } 35 | } 36 | 37 | moves 38 | } 39 | } 40 | 41 | // 2028. Find Missing Observations, Medium 42 | // https://leetcode.com/problems/find-missing-observations/ 43 | impl Solution2 { 44 | pub fn missing_rolls(rolls: Vec, mean: i32, n: i32) -> Vec { 45 | if rolls.is_empty() || n == 0 { 46 | return vec![]; 47 | } 48 | 49 | let m = rolls.len() as i32; 50 | 51 | let have_sum = rolls.iter().sum::(); 52 | let mut missing_sum = (mean * (n + m)) - have_sum; 53 | 54 | let avg_missing = missing_sum / n; 55 | let mut action = true; 56 | if avg_missing > 0 && avg_missing <= 6 { 57 | let mut missing_rolls = vec![avg_missing; n as usize]; 58 | missing_sum -= avg_missing * n; 59 | 'outer: while missing_sum > 0 { 60 | for i in 0..n { 61 | if missing_sum <= 0 || !action { 62 | if !action { 63 | return vec![]; 64 | } 65 | break 'outer; 66 | } 67 | if missing_rolls[i as usize] < 6 { 68 | let add = i32::min(6 - missing_rolls[i as usize], missing_sum); 69 | missing_rolls[i as usize] += add; 70 | missing_sum -= add; 71 | action = true; 72 | } else { 73 | action = false; 74 | } 75 | } 76 | } 77 | 78 | missing_rolls 79 | } else { 80 | return vec![]; 81 | } 82 | } 83 | } 84 | 85 | struct Solution1 {} 86 | struct Solution2 {} 87 | #[cfg(test)] 88 | mod tests { 89 | use super::*; 90 | use crate::{vec_string, vec_vec_i32}; 91 | 92 | #[test] 93 | fn test_minimum_moves() { 94 | assert_eq!(Solution1::minimum_moves("XXX".to_string()), 1); 95 | } 96 | 97 | #[test] 98 | fn test_minimum_moves2() { 99 | assert_eq!(Solution1::minimum_moves("XXOX".to_string()), 2); 100 | } 101 | 102 | #[test] 103 | fn test_minimum_moves3() { 104 | assert_eq!(Solution1::minimum_moves("OOOO".to_string()), 0); 105 | } 106 | 107 | #[test] 108 | fn test_missing_rolls() { 109 | assert_eq!(Solution2::missing_rolls(vec![3, 2, 4, 3], 4, 2), vec![6, 6]); 110 | } 111 | 112 | #[test] 113 | fn test_missing_rolls2() { 114 | assert_eq!(Solution2::missing_rolls(vec![1, 5, 6], 3, 4), vec![3, 2, 2, 2]); 115 | } 116 | 117 | #[test] 118 | fn test_missing_rolls3() { 119 | assert_eq!(Solution2::missing_rolls(vec![1, 2, 3, 4], 6, 4), vec![]); 120 | } 121 | 122 | #[test] 123 | fn test_missing_rolls4() { 124 | assert_eq!(Solution2::missing_rolls(vec![1], 3, 1), vec![5]); 125 | } 126 | 127 | #[test] 128 | fn test_missing_rolls5() { 129 | assert_eq!(Solution2::missing_rolls(vec![3, 5, 4], 5, 3), vec![6, 6, 6]); 130 | } 131 | 132 | #[test] 133 | fn test_missing_rolls6() { 134 | assert_eq!(Solution2::missing_rolls(vec![3, 5, 3], 5, 3), vec![]); 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /src/leetcode/interview/amazon/connect_sticks.rs: -------------------------------------------------------------------------------- 1 | use std::collections::BinaryHeap; 2 | 3 | // 1167. Minimum Cost to Connect Sticks, Medium 4 | // https://leetcode.com/problems/minimum-cost-to-connect-sticks/ 5 | impl Solution { 6 | pub fn connect_sticks(sticks: Vec) -> i32 { 7 | let sticks = sticks.iter().map(|x| -x).collect::>(); 8 | let mut sticks_heap = BinaryHeap::from(sticks); 9 | 10 | let mut cost = 0; 11 | while sticks_heap.len() > 1 { 12 | let stick = sticks_heap.pop().unwrap() + sticks_heap.pop().unwrap(); 13 | sticks_heap.push(stick); 14 | cost += -stick; 15 | } 16 | 17 | cost 18 | } 19 | } 20 | 21 | struct Solution {} 22 | 23 | #[cfg(test)] 24 | mod tests { 25 | use super::*; 26 | use crate::vec_vec_i32; 27 | 28 | #[test] 29 | fn test_connect_sticks() { 30 | assert_eq!(Solution::connect_sticks(vec![2, 4, 3]), 14); 31 | } 32 | 33 | #[test] 34 | fn test_connect_sticks2() { 35 | assert_eq!(Solution::connect_sticks(vec![1, 8, 3, 5]), 30); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/leetcode/interview/amazon/find_circle_num.rs: -------------------------------------------------------------------------------- 1 | // 547. Number of Provinces, Medium 2 | // https://leetcode.com/problems/number-of-provinces/ 3 | impl Solution { 4 | pub fn find_circle_num(mut is_connected: Vec>) -> i32 { 5 | let n = is_connected.len(); 6 | 7 | let mut provinces = 0; 8 | fn bfs(i: usize, is_connected: &mut Vec>) { 9 | let edges = is_connected[i].clone(); 10 | is_connected[i] = vec![]; 11 | 12 | for (i, is_edge) in edges.iter().enumerate() { 13 | if *is_edge == 1 { 14 | bfs(i as usize, is_connected); 15 | } 16 | } 17 | } 18 | 19 | for i in 0..n { 20 | if !is_connected[i].is_empty() { 21 | provinces += 1; 22 | } 23 | bfs(i, &mut is_connected); 24 | } 25 | 26 | provinces 27 | } 28 | } 29 | 30 | struct Solution {} 31 | 32 | #[cfg(test)] 33 | mod tests { 34 | use super::*; 35 | use crate::vec_vec_i32; 36 | 37 | #[test] 38 | fn test_find_circle_num() { 39 | assert_eq!(Solution::find_circle_num(vec_vec_i32![[1, 1, 0], [1, 1, 0], [0, 0, 1]]), 2); 40 | } 41 | 42 | #[test] 43 | fn test_find_circle_num2() { 44 | assert_eq!(Solution::find_circle_num(vec_vec_i32![[1, 0, 0], [0, 1, 0], [0, 0, 1]]), 3); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/leetcode/interview/amazon/first_uniq_char.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | // 387. First Unique Character in a String, Easy 4 | // https://leetcode.com/problems/first-unique-character-in-a-string/ 5 | impl Solution { 6 | pub fn first_uniq_char(s: String) -> i32 { 7 | let mut map = HashMap::::new(); 8 | 9 | for char in s.chars() { 10 | map.entry(char).and_modify(|f| *f += 1).or_insert(1); 11 | } 12 | 13 | for (i, char) in s.chars().enumerate() { 14 | if *map.get(&char).unwrap() == 1 { 15 | return i as i32; 16 | } 17 | } 18 | 19 | -1 20 | } 21 | } 22 | 23 | struct Solution {} 24 | -------------------------------------------------------------------------------- /src/leetcode/interview/amazon/high_five.rs: -------------------------------------------------------------------------------- 1 | use std::collections::{BinaryHeap, HashMap}; 2 | 3 | // 1086. High Five, Easy 4 | // https://leetcode.com/problems/high-five/ 5 | impl Solution { 6 | pub fn high_five(items: Vec>) -> Vec> { 7 | // items[i] = [IDi, scorei] 8 | let mut five_map = HashMap::>::new(); 9 | 10 | let mut ans: Vec> = vec![]; 11 | for item in items.iter() { 12 | let [id, score] = [item[0], item[1]]; 13 | if let std::collections::hash_map::Entry::Vacant(e) = five_map.entry(id) { 14 | e.insert(BinaryHeap::from(vec![-score])); 15 | } else { 16 | five_map.entry(id).and_modify(|h| h.push(-score)); 17 | } 18 | 19 | if five_map.get_mut(&id).unwrap().len() > 5 { 20 | five_map.get_mut(&id).unwrap().pop(); 21 | } 22 | } 23 | 24 | five_map.iter().for_each(|(id, heap)| { 25 | let sum = -heap.iter().sum::(); 26 | ans.push(vec![*id, sum / heap.len() as i32]) 27 | }); 28 | 29 | ans.sort_unstable_by_key(|f| f[0]); 30 | 31 | ans 32 | } 33 | } 34 | 35 | struct Solution {} 36 | 37 | #[cfg(test)] 38 | mod tests { 39 | use super::*; 40 | use crate::vec_vec_i32; 41 | 42 | #[test] 43 | fn test_high_five() { 44 | assert_eq!( 45 | Solution::high_five(vec_vec_i32![ 46 | [1, 91], 47 | [1, 92], 48 | [2, 93], 49 | [2, 97], 50 | [1, 60], 51 | [2, 77], 52 | [1, 65], 53 | [1, 87], 54 | [1, 100], 55 | [2, 100], 56 | [2, 76] 57 | ]), 58 | vec_vec_i32![[1, 87], [2, 88]] 59 | ); 60 | } 61 | 62 | #[test] 63 | fn test_high_five2() { 64 | assert_eq!( 65 | Solution::high_five(vec_vec_i32![ 66 | [1, 100], 67 | [7, 100], 68 | [1, 100], 69 | [7, 100], 70 | [1, 100], 71 | [7, 100], 72 | [1, 100], 73 | [7, 100], 74 | [1, 100], 75 | [7, 100] 76 | ]), 77 | vec_vec_i32![[1, 100], [7, 100]] 78 | ); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/leetcode/interview/amazon/is_robot_bounded.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashSet; 2 | 3 | // 1041. Robot Bounded In Circle, Medium 4 | // https://leetcode.com/problems/robot-bounded-in-circle/submissions/ 5 | impl Solution { 6 | pub fn is_robot_bounded(instructions: String) -> bool { 7 | #[derive(PartialEq, Eq)] 8 | enum Direction { 9 | North, 10 | East, 11 | South, 12 | West, 13 | } 14 | 15 | let mut pos = (0, 0); 16 | let mut direction = Direction::North; 17 | 18 | for instruction in instructions.chars() { 19 | // move 20 | match instruction { 21 | 'G' => match direction { 22 | Direction::North => pos.1 += 1, 23 | Direction::East => pos.0 += 1, 24 | Direction::South => pos.1 += -1, 25 | Direction::West => pos.0 += -1, 26 | }, 27 | 'L' => match direction { 28 | Direction::North => direction = Direction::West, 29 | Direction::East => direction = Direction::North, 30 | Direction::South => direction = Direction::East, 31 | Direction::West => direction = Direction::South, 32 | }, 33 | 'R' => match direction { 34 | Direction::North => direction = Direction::East, 35 | Direction::East => direction = Direction::South, 36 | Direction::South => direction = Direction::West, 37 | Direction::West => direction = Direction::North, 38 | }, 39 | _ => {} 40 | } 41 | } 42 | 43 | pos == (0, 0) || direction != Direction::North 44 | } 45 | } 46 | 47 | struct Solution {} 48 | 49 | #[cfg(test)] 50 | mod tests { 51 | use super::*; 52 | use crate::vec_string; 53 | 54 | #[test] 55 | fn test_is_robot_bounded() { 56 | assert_eq!(Solution::is_robot_bounded("GGLLGG".to_string()), true); 57 | } 58 | 59 | #[test] 60 | fn test_is_robot_bounded2() { 61 | assert_eq!(Solution::is_robot_bounded("GG".to_string()), false); 62 | } 63 | 64 | #[test] 65 | fn test_is_robot_bounded3() { 66 | assert_eq!(Solution::is_robot_bounded("GL".to_string()), true); 67 | } 68 | 69 | #[test] 70 | fn test_is_robot_bounded4() { 71 | assert_eq!(Solution::is_robot_bounded("GLGLGGLGL".to_string()), false); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/leetcode/interview/amazon/maximum_units.rs: -------------------------------------------------------------------------------- 1 | // 1710. Maximum Units on a Truck, Easy 2 | // https://leetcode.com/problems/maximum-units-on-a-truck/ 3 | impl Solution { 4 | pub fn maximum_units(mut box_types: Vec>, mut truck_size: i32) -> i32 { 5 | box_types.sort_unstable_by(|a, b| b[1].cmp(&a[1])); 6 | 7 | let mut loaded_boxes = 0; 8 | 9 | for box_type in box_types { 10 | if truck_size > box_type[0] { 11 | truck_size -= box_type[0]; 12 | loaded_boxes += box_type[0] * box_type[1]; 13 | } else { 14 | loaded_boxes += truck_size * box_type[1]; 15 | return loaded_boxes; 16 | } 17 | } 18 | 19 | loaded_boxes 20 | } 21 | } 22 | 23 | struct Solution {} 24 | 25 | #[cfg(test)] 26 | mod tests { 27 | use super::*; 28 | use crate::vec_vec_i32; 29 | 30 | #[test] 31 | fn test_maximum_units() { 32 | assert_eq!(Solution::maximum_units(vec_vec_i32![[1, 3], [2, 2], [3, 1]], 4), 8); 33 | } 34 | 35 | #[test] 36 | fn test_maximum_units2() { 37 | assert_eq!(Solution::maximum_units(vec_vec_i32![[5, 10], [2, 5], [4, 7], [3, 9]], 10), 91); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/leetcode/interview/amazon/mod.rs: -------------------------------------------------------------------------------- 1 | automod::dir!("src/leetcode/interview/amazon"); -------------------------------------------------------------------------------- /src/leetcode/interview/amazon/reorder_log_files.rs: -------------------------------------------------------------------------------- 1 | // 937. Reorder Data in Log Files, Easy 2 | // https://leetcode.com/problems/reorder-data-in-log-files/ 3 | impl Solution { 4 | pub fn reorder_log_files(logs: Vec) -> Vec { 5 | let mut letter_logs = vec![]; 6 | let mut digit_logs = vec![]; 7 | 8 | for log in logs { 9 | let chunks = log.split(' ').map(|s| s.to_string()).collect::>(); 10 | let id = chunks[0].clone(); 11 | let msg = &chunks[1..]; 12 | let kind = { 13 | if msg[0].chars().next().unwrap().is_alphabetic() { 14 | 0 // letter 15 | } else { 16 | 1 // digit 17 | } 18 | }; 19 | 20 | if kind == 0 { 21 | letter_logs.push((id, msg.join(" "))); 22 | } else { 23 | digit_logs.push(log); 24 | } 25 | } 26 | 27 | letter_logs.sort_by(|a, b| { 28 | let (id_a, msg_a) = a; 29 | let (id_b, msg_b) = b; 30 | msg_a.cmp(msg_b).then_with(|| id_a.cmp(id_b)) 31 | }); 32 | 33 | letter_logs.into_iter().map(|(id, msg)| format!("{} {}", id, msg)).into_iter().chain(digit_logs).collect() 34 | } 35 | } 36 | 37 | struct Solution {} 38 | 39 | #[cfg(test)] 40 | mod tests { 41 | use super::*; 42 | use crate::vec_string; 43 | 44 | #[test] 45 | fn test_reorder_log_files() { 46 | assert_eq!( 47 | Solution::reorder_log_files(vec_string!["dig1 8 1 5 1", "let1 art can", "dig2 3 6", "let2 own kit dig", "let3 art zero"]), 48 | vec_string!["let1 art can", "let3 art zero", "let2 own kit dig", "dig1 8 1 5 1", "dig2 3 6"] 49 | ); 50 | } 51 | 52 | #[test] 53 | fn test_reorder_log_files2() { 54 | assert_eq!( 55 | Solution::reorder_log_files(vec_string!["a1 9 2 3 1", "g1 act car", "zo4 4 7", "ab1 off key dog", "a8 act zoo"]), 56 | vec_string!["g1 act car", "a8 act zoo", "ab1 off key dog", "a1 9 2 3 1", "zo4 4 7"] 57 | ); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/leetcode/interview/amazon/search.rs: -------------------------------------------------------------------------------- 1 | // 33. Search in Rotated Sorted Array, Medium 2 | // https://leetcode.com/problems/search-in-rotated-sorted-array/ 3 | impl Solution { 4 | pub fn search(nums: Vec, target: i32) -> i32 { 5 | let mut nums = nums.iter().enumerate().map(|(i, n)| (*n, i)).collect::>(); 6 | nums.sort_unstable(); 7 | 8 | let i = nums.binary_search_by(|p| p.0.cmp(&target)); 9 | match i { 10 | Ok(i) => nums[i].1 as i32, 11 | Err(_) => -1, 12 | } 13 | } 14 | } 15 | 16 | struct Solution {} 17 | -------------------------------------------------------------------------------- /src/leetcode/interview/amazon/suggested_products.rs: -------------------------------------------------------------------------------- 1 | // 1268. Search Suggestions System, Medium 2 | // https://leetcode.com/problems/search-suggestions-system/ 3 | impl Solution { 4 | pub fn suggested_products(products: Vec, search_word: String) -> Vec> { 5 | let mut suggested_products = vec![]; 6 | for i in 0..search_word.len() { 7 | println!("{}", &search_word[..i + 1]); 8 | let mut filtered = products 9 | .iter() 10 | .filter(|p| p.starts_with(&search_word[..i + 1])) 11 | .map(|p| p.to_string()) 12 | .collect::>(); 13 | filtered.sort(); 14 | 15 | suggested_products.push(filtered.iter().take(3).cloned().collect::>()); 16 | } 17 | 18 | suggested_products 19 | } 20 | } 21 | 22 | struct Solution {} 23 | 24 | #[cfg(test)] 25 | mod tests { 26 | use super::*; 27 | use crate::{vec_string, vec_vec_string}; 28 | 29 | #[test] 30 | fn test_suggested_products() { 31 | assert_eq!( 32 | Solution::suggested_products(vec_string!["mobile", "mouse", "moneypot", "monitor", "mousepad"], "mouse".to_string()), 33 | vec_vec_string![ 34 | ["mobile", "moneypot", "monitor"], 35 | ["mobile", "moneypot", "monitor"], 36 | ["mouse", "mousepad"], 37 | ["mouse", "mousepad"], 38 | ["mouse", "mousepad"] 39 | ] 40 | ); 41 | } 42 | 43 | #[test] 44 | fn test_suggested_products2() { 45 | assert_eq!( 46 | Solution::suggested_products(vec_string!["havana"], "havana".to_string()), 47 | vec_vec_string![["havana"], ["havana"], ["havana"], ["havana"], ["havana"], ["havana"]] 48 | ); 49 | } 50 | 51 | #[test] 52 | fn test_suggested_products3() { 53 | assert_eq!( 54 | Solution::suggested_products(vec_string!["bags", "baggage", "banner", "box", "cloths"], "bags".to_string()), 55 | vec_vec_string![["baggage", "bags", "banner"], ["baggage", "bags", "banner"], ["baggage", "bags"], ["bags"]] 56 | ); 57 | } 58 | 59 | #[test] 60 | fn test_suggested_products4() { 61 | assert_eq!( 62 | Solution::suggested_products(vec_string!["havana"], "tatiana".to_string()), 63 | vec_vec_string![[], [], [], [], [], [], []] 64 | ); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/leetcode/interview/amazon/sum_even_grandparent.rs: -------------------------------------------------------------------------------- 1 | // Definition for a binary tree node. 2 | #[derive(Debug, PartialEq, Eq)] 3 | pub struct TreeNode { 4 | pub val: i32, 5 | pub left: Option>>, 6 | pub right: Option>>, 7 | } 8 | 9 | impl TreeNode { 10 | #[inline] 11 | pub fn new(val: i32) -> Self { 12 | TreeNode { val, left: None, right: None } 13 | } 14 | } 15 | 16 | use std::cell::RefCell; 17 | use std::rc::Rc; 18 | 19 | // 1315. Sum of Nodes with Even-Valued Grandparent, Medium 20 | // https://leetcode.com/problems/sum-of-nodes-with-even-valued-grandparent/ 21 | impl Solution { 22 | pub fn sum_even_grandparent(root: Option>>) -> i32 { 23 | fn bfs(node: Option>>, parent_val: i32, grand_parent_val: i32, ans: &mut i32) { 24 | if node.is_some() { 25 | let node = node.as_ref().unwrap().borrow(); 26 | 27 | if grand_parent_val != -1 && grand_parent_val % 2 == 0 { 28 | *ans += node.val; 29 | } 30 | 31 | bfs(node.left.clone(), node.val, parent_val, ans); 32 | bfs(node.left.clone(), node.val, parent_val, ans); 33 | } 34 | } 35 | 36 | let mut ans = 0; 37 | 38 | bfs(root, -1, -1, &mut ans); 39 | ans 40 | } 41 | } 42 | 43 | struct Solution {} 44 | -------------------------------------------------------------------------------- /src/leetcode/interview/mod.rs: -------------------------------------------------------------------------------- 1 | mod amazon; 2 | mod robinhood; 3 | mod uber; 4 | -------------------------------------------------------------------------------- /src/leetcode/interview/robinhood/alert_names.rs: -------------------------------------------------------------------------------- 1 | use std::collections::{HashMap, HashSet}; 2 | 3 | // 1604. Alert Using Same Key-Card Three or More Times in a One Hour Period, Medium 4 | // https://leetcode.com/problems/alert-using-same-key-card-three-or-more-times-in-a-one-hour-period/ 5 | impl Solution { 6 | pub fn alert_names(key_name: Vec, key_time: Vec) -> Vec { 7 | let n = key_name.len(); 8 | let mut time_map = HashMap::>::new(); 9 | 10 | // HH:MM 11 | fn parse_time(time: &String) -> i32 { 12 | let chars = time.chars().collect::>(); 13 | ((chars[0].to_digit(10).unwrap() * 10 + chars[1].to_digit(10).unwrap()) * 60 + (chars[3].to_digit(10).unwrap() * 10 + chars[4].to_digit(10).unwrap())) as i32 14 | } 15 | 16 | let mut ans = HashSet::::new(); 17 | for i in 0..n { 18 | let name = &key_name[i]; 19 | let time = parse_time(&key_time[i]); 20 | 21 | time_map.entry(name.clone()).or_insert(Vec::::new()); 22 | time_map.get_mut(name).unwrap().push(time); 23 | } 24 | 25 | time_map.iter_mut().for_each(|(_, times)| { 26 | times.sort_unstable(); 27 | }); 28 | 29 | time_map.iter().for_each(|(name, times)| { 30 | let mut i = 0; 31 | while times.len() - i > 2 { 32 | if i32::abs(times[i] - times[i + 2]) <= 60 { 33 | ans.insert(name.clone()); 34 | } 35 | i += 1; 36 | } 37 | }); 38 | 39 | let mut ans = ans.iter().cloned().collect::>(); 40 | ans.sort_unstable(); 41 | ans 42 | } 43 | } 44 | 45 | struct Solution {} 46 | 47 | #[cfg(test)] 48 | mod tests { 49 | use super::*; 50 | use crate::vec_string; 51 | 52 | #[test] 53 | fn test_alert_names() { 54 | assert_eq!( 55 | Solution::alert_names( 56 | vec_string!["daniel", "daniel", "daniel", "luis", "luis", "luis", "luis"], 57 | vec_string!["10:00", "10:40", "11:00", "09:00", "11:00", "13:00", "15:00"] 58 | ), 59 | vec_string!["daniel"] 60 | ); 61 | } 62 | 63 | #[test] 64 | fn test_alert_names2() { 65 | assert_eq!( 66 | Solution::alert_names( 67 | vec_string!["alice", "alice", "alice", "bob", "bob", "bob", "bob"], 68 | vec_string!["12:01", "12:00", "18:00", "21:00", "21:20", "21:30", "23:00"] 69 | ), 70 | vec_string!["bob"] 71 | ); 72 | } 73 | 74 | #[test] 75 | fn test_alert_names3() { 76 | assert_eq!( 77 | Solution::alert_names(vec_string!["john", "john", "john"], vec_string!["23:58", "23:59", "00:01"]), 78 | vec_string![] 79 | ); 80 | } 81 | 82 | #[test] 83 | fn test_alert_names4() { 84 | assert_eq!( 85 | Solution::alert_names( 86 | vec_string!["leslie", "leslie", "leslie", "clare", "clare", "clare", "clare"], 87 | vec_string!["13:00", "13:20", "14:00", "18:00", "18:51", "19:30", "19:49"] 88 | ), 89 | vec_string!["clare", "leslie"] 90 | ); 91 | } 92 | 93 | #[test] 94 | fn test_alert_names5() { 95 | assert_eq!( 96 | Solution::alert_names( 97 | vec_string!["a", "a", "a", "a", "a", "a", "b", "b", "b", "b", "b"], 98 | vec_string!["23:27", "03:14", "12:57", "13:35", "13:18", "21:58", "22:39", "10:49", "19:37", "14:14", "10:41"] 99 | ), 100 | vec_string!["a"] 101 | ); 102 | } 103 | 104 | #[test] 105 | fn test_alert_names6() { 106 | assert_eq!( 107 | Solution::alert_names( 108 | vec_string!["a", "a", "a", "a", "a", "b", "b", "b", "b", "b", "b"], 109 | vec_string!["23:20", "11:09", "23:30", "23:02", "15:28", "22:57", "23:40", "03:43", "21:55", "20:38", "00:19"] 110 | ), 111 | vec_string!["a"] 112 | ); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/leetcode/interview/robinhood/mod.rs: -------------------------------------------------------------------------------- 1 | automod::dir!("src/leetcode/interview/robinhood"); -------------------------------------------------------------------------------- /src/leetcode/interview/uber/mod.rs: -------------------------------------------------------------------------------- 1 | automod::dir!("src/leetcode/interview/uber"); -------------------------------------------------------------------------------- /src/leetcode/interview/uber/num_buses_to_destination.rs: -------------------------------------------------------------------------------- 1 | use std::collections::{HashMap, HashSet, VecDeque}; 2 | 3 | // 815. Bus Routes, Hard 4 | // https://leetcode.com/problems/bus-routes/ 5 | impl Solution { 6 | pub fn num_buses_to_destination(routes: Vec>, source: i32, target: i32) -> i32 { 7 | let mut hm: HashMap> = HashMap::new(); 8 | 9 | for (bus, route) in routes.iter().enumerate() { 10 | let bus = bus as i32; 11 | 12 | let mut route = route.clone(); 13 | route.push(route[0]); 14 | 15 | for j in 0..route.len() - 1 { 16 | let j = j as i32; 17 | hm.entry(route[j as usize]) 18 | .and_modify(|f| f.push((route[j as usize + 1], bus))) 19 | .or_insert(vec![(route[j as usize + 1], bus)]); 20 | } 21 | } 22 | 23 | let mut queue: VecDeque<(i32, HashSet)> = VecDeque::new(); 24 | queue.push_back((source, HashSet::::new())); 25 | 26 | let mut seen: HashSet = HashSet::new(); 27 | 28 | let mut min_busses = usize::MAX; 29 | 30 | while !queue.is_empty() { 31 | let (stop, busses) = queue.pop_front().unwrap(); 32 | 33 | if stop == target { 34 | min_busses = min_busses.min(busses.len()); 35 | } 36 | 37 | seen.insert(stop); 38 | 39 | for edge in hm.get(&stop).unwrap_or(&vec![]) { 40 | if seen.contains(&edge.0) { 41 | continue; 42 | } 43 | 44 | let mut busses = busses.clone(); 45 | busses.insert(edge.1); 46 | queue.push_back((edge.0, busses)); 47 | } 48 | } 49 | 50 | min_busses as i32 51 | } 52 | } 53 | 54 | struct Solution {} 55 | 56 | #[cfg(test)] 57 | mod tests { 58 | use super::*; 59 | use crate::vec_vec_i32; 60 | 61 | #[test] 62 | fn test_num_buses_to_destination() { 63 | assert_eq!(Solution::num_buses_to_destination(vec_vec_i32![[1, 2, 7], [3, 6, 7]], 1, 6), 2); 64 | } 65 | 66 | #[test] 67 | fn test_num_buses_to_destination2() { 68 | assert_eq!( 69 | Solution::num_buses_to_destination(vec_vec_i32![[7, 12], [4, 5, 15], [6], [15, 19], [9, 12, 13]], 15, 12), 70 | -1 71 | ); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/leetcode/mod.rs: -------------------------------------------------------------------------------- 1 | mod challenge; 2 | mod contest; 3 | mod interview; 4 | mod problem; 5 | mod top_interview; 6 | #[cfg_attr(test, macro_use)] 7 | mod util; 8 | -------------------------------------------------------------------------------- /src/leetcode/problem/add_operators.rs: -------------------------------------------------------------------------------- 1 | // 282. Expression Add Operators, Hard 2 | // https://leetcode.com/problems/expression-add-operators/ 3 | impl Solution { 4 | pub fn add_operators(num: String, target: i32) -> Vec { 5 | let mut ans = vec![]; 6 | 7 | fn force(num: &String, target: i32, prev_effect: Option, i: i32, equation: String, res: i32, ans: &mut Vec) { 8 | if i == num.len() as i32 { 9 | if target == res { 10 | ans.push(equation); 11 | } 12 | } else if i < num.len() as i32 { 13 | let digit = num[i as usize..(i + 1) as usize].parse::().unwrap(); 14 | let digit_str = &digit.to_string(); 15 | 16 | if i == 0 { 17 | force(num, target, None, i + 1, digit.to_string(), digit, ans); 18 | } else { 19 | force(num, target, Some(digit), i + 1, equation.clone() + "+" + digit_str, res + digit, ans); 20 | force(num, target, Some(-digit), i + 1, equation.clone() + "-" + digit_str, res - digit, ans); 21 | if prev_effect.is_some() { 22 | force( 23 | num, 24 | target, 25 | None, 26 | i + 1, 27 | equation + "*" + digit_str, 28 | (res - prev_effect.unwrap()) + (prev_effect.unwrap() * digit), 29 | ans, 30 | ); 31 | } else { 32 | force(num, target, None, i + 1, equation + "*" + digit_str, res * digit, ans); 33 | } 34 | } 35 | } 36 | } 37 | 38 | force(&num, target, None, 0, "".to_string(), 0, &mut ans); 39 | 40 | ans 41 | } 42 | } 43 | 44 | struct Solution {} 45 | 46 | #[cfg(test)] 47 | mod tests { 48 | use super::*; 49 | 50 | #[test] 51 | fn test_add_operators() { 52 | assert_eq!(Solution::add_operators("123".to_string(), 6), vec!["1+2+3", "1*2*3"]); 53 | } 54 | 55 | #[test] 56 | fn test_add_operators2() { 57 | assert_eq!(Solution::add_operators("1".to_string(), 1), vec!["1"]); 58 | } 59 | 60 | #[test] 61 | fn test_add_operators3() { 62 | assert_eq!(Solution::add_operators("12".to_string(), 4), [] as [&str; 0]); 63 | } 64 | 65 | #[test] 66 | fn test_add_operators4() { 67 | assert_eq!(Solution::add_operators("232".to_string(), 8), vec!["2+3*2", "2*3+2"]); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/leetcode/problem/broken_calc.rs: -------------------------------------------------------------------------------- 1 | // 991. Broken Calculator, Medium 2 | // https://leetcode.com/problems/broken-calculator/ 3 | impl Solution { 4 | pub fn broken_calc(start_value: i32, target: i32) -> i32 { 5 | let mut ops = 0; 6 | let mut value = target; 7 | 8 | while value > start_value { 9 | if value % 2 == 1 { 10 | value += 1; 11 | ops += 1; 12 | } 13 | 14 | value /= 2; 15 | ops += 1; 16 | } 17 | 18 | ops += start_value - value; 19 | ops 20 | } 21 | } 22 | 23 | struct Solution {} 24 | 25 | #[cfg(test)] 26 | mod tests { 27 | use super::*; 28 | use crate::vec_vec_i32; 29 | 30 | #[test] 31 | fn test_broken_calc() { 32 | assert_eq!(Solution::broken_calc(2, 3), 2); 33 | } 34 | 35 | #[test] 36 | fn test_broken_calc2() { 37 | assert_eq!(Solution::broken_calc(5, 8), 2); 38 | } 39 | 40 | #[test] 41 | fn test_broken_calc3() { 42 | assert_eq!(Solution::broken_calc(3, 10), 3); 43 | } 44 | 45 | #[test] 46 | fn test_broken_calc4() { 47 | assert_eq!(Solution::broken_calc(1024, 1), 1023); 48 | } 49 | 50 | #[test] 51 | fn test_broken_calc5() { 52 | assert_eq!(Solution::broken_calc(1, 1000000000), 39); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/leetcode/problem/bst_from_preorder.rs: -------------------------------------------------------------------------------- 1 | // Definition for a binary tree node. 2 | #[derive(Debug, PartialEq, Eq)] 3 | pub struct TreeNode { 4 | pub val: i32, 5 | pub left: Option>>, 6 | pub right: Option>>, 7 | } 8 | 9 | impl TreeNode { 10 | #[inline] 11 | pub fn new(val: i32) -> Self { 12 | TreeNode { val, left: None, right: None } 13 | } 14 | } 15 | 16 | use std::cell::RefCell; 17 | use std::rc::Rc; 18 | 19 | // 1008. Construct Binary Search Tree from Preorder Traversal, Medium 20 | // https://leetcode.com/problems/construct-binary-search-tree-from-preorder-traversal/ 21 | impl Solution { 22 | pub fn bst_from_preorder(preorder: Vec) -> Option>> { 23 | fn helper(i: &mut usize, preorder: &Vec, lower: i32, upper: i32) -> Option>> { 24 | let n = preorder.len(); 25 | 26 | if *i >= n { 27 | return None; 28 | } 29 | 30 | let val = preorder[*i]; 31 | if val < lower || val > upper { 32 | return None; 33 | } 34 | 35 | *i += 1; 36 | 37 | let root = Rc::new(RefCell::new(TreeNode::new(val))); 38 | root.borrow_mut().left = helper(i, preorder, lower, val); 39 | root.borrow_mut().right = helper(i, preorder, val, upper); 40 | 41 | Some(root) 42 | } 43 | 44 | let mut i = 0; 45 | helper(&mut i, &preorder, i32::MIN, i32::MAX) 46 | } 47 | } 48 | 49 | struct Solution {} 50 | -------------------------------------------------------------------------------- /src/leetcode/problem/can_complete_circuit.rs: -------------------------------------------------------------------------------- 1 | // 134. Gas Station, Medium 2 | // https://leetcode.com/problems/gas-station/ 3 | impl Solution { 4 | pub fn can_complete_circuit(gas: Vec, cost: Vec) -> i32 { 5 | let n = gas.len(); 6 | 7 | for i in 0..n { 8 | let mut pos = i; 9 | let mut dist = 0; 10 | let mut tank = 0; 11 | 12 | while dist <= n { 13 | tank += gas[pos] - cost[pos]; 14 | if tank < 0 { 15 | break; 16 | } else { 17 | pos += 1; 18 | pos %= n; 19 | dist += 1; 20 | } 21 | } 22 | 23 | if dist >= n { 24 | return i as i32; 25 | } 26 | } 27 | 28 | -1 29 | } 30 | } 31 | 32 | struct Solution {} 33 | 34 | #[cfg(test)] 35 | mod tests { 36 | use super::*; 37 | use crate::vec_vec_i32; 38 | 39 | #[test] 40 | fn test_can_complete_circuit() { 41 | assert_eq!(Solution::can_complete_circuit(vec![1, 2, 3, 4, 5], vec![3, 4, 5, 1, 2]), 3); 42 | } 43 | 44 | #[test] 45 | fn test_can_complete_circuit2() { 46 | assert_eq!(Solution::can_complete_circuit(vec![2, 3, 4], vec![3, 4, 3]), -1); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/leetcode/problem/can_construct.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | // 1400. Construct K Palindrome Strings, Medium 4 | // https://leetcode.com/problems/construct-k-palindrome-strings/ 5 | impl Solution { 6 | pub fn can_construct(s: String, k: i32) -> bool { 7 | let mut counter: HashMap = HashMap::new(); 8 | 9 | let n = s.len() as i32; 10 | for ch in s.chars() { 11 | counter.entry(ch).and_modify(|c| *c += 1).or_insert(1); 12 | } 13 | 14 | let mut odds = 0; 15 | 16 | for (_k, v) in counter { 17 | if v % 2 != 0 { 18 | odds += 1; 19 | } 20 | } 21 | 22 | return n >= k && odds <= k; 23 | } 24 | } 25 | 26 | struct Solution {} 27 | -------------------------------------------------------------------------------- /src/leetcode/problem/can_three_parts_equal_sum.rs: -------------------------------------------------------------------------------- 1 | // 1013. Partition Array Into Three Parts With Equal Sum, Easy 2 | // https://leetcode.com/problems/partition-array-into-three-parts-with-equal-sum/ 3 | impl Solution { 4 | pub fn can_three_parts_equal_sum(arr: Vec) -> bool { 5 | let sum = arr.iter().sum::(); 6 | 7 | if sum % 3 != 0 { 8 | return false; 9 | } 10 | 11 | let target = sum / 3; 12 | let mut buckets = [0, 0, 0]; 13 | let mut buckets_size = [0, 0, 0]; 14 | let mut i = 0; 15 | for num in arr.iter() { 16 | buckets[i % 3] += num; 17 | buckets_size[i % 3] += 1; 18 | if buckets[i % 3] == target { 19 | i += 1; 20 | } 21 | } 22 | println!("{:?}", buckets); 23 | buckets_size[0] > 0 && buckets_size[1] > 0 && buckets_size[2] > 0 && buckets[0] == buckets[1] && buckets[1] == buckets[2] 24 | } 25 | } 26 | 27 | struct Solution {} 28 | 29 | #[cfg(test)] 30 | mod tests { 31 | use super::*; 32 | 33 | #[test] 34 | fn test_can_three_parts_equal_sum() { 35 | assert_eq!(Solution::can_three_parts_equal_sum(vec![0, 2, 1, -6, 6, -7, 9, 1, 2, 0, 1]), true); 36 | } 37 | 38 | #[test] 39 | fn test_can_three_parts_equal_sum2() { 40 | assert_eq!(Solution::can_three_parts_equal_sum(vec![0, 2, 1, -6, 6, -7, 9, 1, 2, 0, 1]), true); 41 | } 42 | 43 | #[test] 44 | fn test_can_three_parts_equal_sum3() { 45 | assert_eq!(Solution::can_three_parts_equal_sum(vec![0, 2, 1, -6, 6, -7, 9, 1, 2, 0, 1]), true); 46 | } 47 | 48 | #[test] 49 | fn test_can_three_parts_equal_sum4() { 50 | assert_eq!(Solution::can_three_parts_equal_sum(vec![1, -1, 1, -1]), false); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/leetcode/problem/can_visit_all_rooms.rs: -------------------------------------------------------------------------------- 1 | use std::collections::VecDeque; 2 | 3 | // 841. Keys and Rooms, Medium 4 | // https://leetcode.com/problems/keys-and-rooms/ 5 | impl Solution { 6 | pub fn can_visit_all_rooms(rooms: Vec>) -> bool { 7 | let mut rooms = rooms; 8 | let n = rooms.len(); 9 | 10 | let mut visited = vec![false; n]; 11 | 12 | let mut q: VecDeque = VecDeque::new(); 13 | q.push_back(0); 14 | visited[0] = true; 15 | 16 | while !q.is_empty() { 17 | let room = q.pop_front().unwrap() as usize; 18 | visited[room] = true; 19 | for key in &rooms[room] { 20 | q.push_back(*key); 21 | } 22 | rooms[room as usize] = vec![]; 23 | } 24 | 25 | visited.iter().all(|v| *v) 26 | } 27 | } 28 | 29 | struct Solution {} 30 | -------------------------------------------------------------------------------- /src/leetcode/problem/climb_stairs.rs: -------------------------------------------------------------------------------- 1 | // 70. Climbing Stairs, Easy 2 | // https://leetcode.com/problems/climbing-stairs/ 3 | impl Solution { 4 | pub fn climb_stairs(n: i32) -> i32 { 5 | let mut dp = vec![0; n.max(4) as usize + 1]; 6 | dp[0] = 0; 7 | dp[1] = 1; 8 | dp[2] = 2; 9 | dp[3] = 3; 10 | for i in 4..=n as usize { 11 | dp[i] = dp[i - 1] + dp[i - 2]; 12 | } 13 | dp[n as usize] 14 | } 15 | } 16 | 17 | struct Solution {} 18 | 19 | #[cfg(test)] 20 | mod tests { 21 | use super::*; 22 | 23 | #[test] 24 | fn test_climb_stairs() { 25 | assert_eq!(Solution::climb_stairs(2), 2); 26 | } 27 | 28 | #[test] 29 | fn test_climb_stairs2() { 30 | assert_eq!(Solution::climb_stairs(3), 3); 31 | } 32 | 33 | #[test] 34 | fn test_climb_stairs3() { 35 | assert_eq!(Solution::climb_stairs(4), 5); 36 | } 37 | } 38 | 39 | -------------------------------------------------------------------------------- /src/leetcode/problem/coin_change.rs: -------------------------------------------------------------------------------- 1 | // 322. Coin Change, Medium 2 | // https://leetcode.com/problems/coin-change/ 3 | impl Solution { 4 | pub fn coin_change(coins: Vec, amount: i32) -> i32 { 5 | let _n = coins.len(); 6 | let mut dp = vec![amount + 1; amount as usize + 1]; 7 | 8 | dp[0] = 0; 9 | 10 | for i in 1..=amount { 11 | for coin in coins.iter() { 12 | if i >= *coin { 13 | dp[i as usize] = dp[i as usize].min(dp[(i - *coin) as usize] + 1); 14 | } 15 | } 16 | } 17 | 18 | if dp.last().unwrap() > &amount { 19 | -1 20 | } else { 21 | *dp.last().unwrap() as i32 22 | } 23 | } 24 | } 25 | 26 | struct Solution {} 27 | 28 | #[cfg(test)] 29 | mod tests { 30 | use super::*; 31 | use crate::vec_vec_i32; 32 | 33 | #[test] 34 | fn test_coin_change() { 35 | assert_eq!(Solution::coin_change(vec![1, 2, 5], 11), 3); 36 | } 37 | 38 | #[test] 39 | fn test_coin_change2() { 40 | assert_eq!(Solution::coin_change(vec![2], 3), -1); 41 | } 42 | 43 | #[test] 44 | fn test_coin_change3() { 45 | assert_eq!(Solution::coin_change(vec![1], 0), 0); 46 | } 47 | 48 | #[test] 49 | fn test_coin_change4() { 50 | assert_eq!(Solution::coin_change(vec![1], 1), 1); 51 | } 52 | 53 | #[test] 54 | fn test_coin_change5() { 55 | assert_eq!(Solution::coin_change(vec![1], 2), 2); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/leetcode/problem/contain_virus.rs: -------------------------------------------------------------------------------- 1 | use std::collections::VecDeque; 2 | 3 | // 749. Contain Virus, Hard 4 | // https://leetcode.com/problems/contain-virus/ 5 | impl Solution { 6 | pub fn contain_virus(mut is_infected: Vec>) -> i32 { 7 | fn find_regions(grid: &mut Vec>, start: (i32, i32)) -> (Vec<(i32, i32)>, Vec<(i32, i32)>) { 8 | let mut regions = Vec::<(i32, i32)>::new(); 9 | let mut neighbors = Vec::<(i32, i32)>::new(); 10 | let directions = vec![(0, 1), (0, -1), (1, 0), (-1, 0)]; 11 | 12 | let mut q = VecDeque::<(i32, i32)>::new(); 13 | q.push_back(start); 14 | 15 | while !q.is_empty() { 16 | let pos = q.pop_back().unwrap(); 17 | 18 | if grid[pos.0 as usize][pos.1 as usize] == 1 { 19 | grid[pos.0 as usize][pos.1 as usize] = 2; 20 | regions.push(pos); 21 | for direction in directions.iter() { 22 | let next = (pos.0 + direction.0, pos.1 + direction.1); 23 | if next.0 < 0 || next.1 < 0 || next.0 >= grid.len() as i32 || next.1 >= grid[0].len() as i32 { 24 | continue; 25 | } 26 | q.push_back(next); 27 | } 28 | } else if grid[pos.0 as usize][pos.1 as usize] == 0 { 29 | neighbors.push(pos); 30 | } 31 | } 32 | 33 | (regions, neighbors) 34 | } 35 | 36 | let mut walls = 0; 37 | let [n, m] = [is_infected.len(), is_infected[0].len()]; 38 | let mut sim = true; 39 | 40 | while sim { 41 | sim = false; 42 | 43 | let mut state = is_infected.clone(); 44 | let mut state_regions = Vec::<(Vec<(i32, i32)>, Vec<(i32, i32)>)>::new(); 45 | for i in 0..n { 46 | for j in 0..m { 47 | if state[i][j] == 1 { 48 | let (regions, neighbors) = find_regions(&mut state, (i as i32, j as i32)); 49 | state_regions.push((regions, neighbors)); 50 | } 51 | } 52 | } 53 | 54 | // find biggest threat 55 | state_regions.sort_unstable_by(|a, b| a.1.len().cmp(&b.1.len())); 56 | 57 | // build walls 58 | if !state_regions.is_empty() { 59 | sim = true; 60 | let biggest_threat = state_regions.pop().unwrap(); 61 | walls += biggest_threat.1.len() as i32; 62 | for pos in biggest_threat.0 { 63 | is_infected[pos.0 as usize][pos.1 as usize] = 2; 64 | } 65 | } 66 | 67 | // spread the virus 68 | for threat in state_regions { 69 | for pos in threat.1 { 70 | is_infected[pos.0 as usize][pos.1 as usize] = 1; 71 | } 72 | } 73 | } 74 | 75 | walls 76 | } 77 | } 78 | 79 | struct Solution {} 80 | 81 | #[cfg(test)] 82 | mod tests { 83 | use super::*; 84 | use crate::vec_vec_i32; 85 | 86 | #[test] 87 | fn test_is_infected() { 88 | assert_eq!( 89 | Solution::contain_virus(vec_vec_i32![ 90 | [0, 1, 0, 0, 0, 0, 0, 1], 91 | [0, 1, 0, 0, 0, 0, 0, 1], 92 | [0, 0, 0, 0, 0, 0, 0, 1], 93 | [0, 0, 0, 0, 0, 0, 0, 0] 94 | ]), 95 | 10 96 | ); 97 | } 98 | 99 | #[test] 100 | fn test_is_infected2() { 101 | assert_eq!(Solution::contain_virus(vec_vec_i32![[1, 1, 1], [1, 0, 1], [1, 1, 1]]), 4); 102 | } 103 | 104 | #[test] 105 | fn test_is_infected3() { 106 | assert_eq!( 107 | Solution::contain_virus(vec_vec_i32![[1, 1, 1, 0, 0, 0, 0, 0, 0], [1, 0, 1, 0, 1, 1, 1, 1, 1], [1, 1, 1, 0, 0, 0, 0, 0, 0]]), 108 | 13 109 | ); 110 | } 111 | 112 | #[test] 113 | fn test_is_infected4() { 114 | assert_eq!( 115 | Solution::contain_virus(vec_vec_i32![[0, 1, 0, 0, 0, 0, 0, 1], [0, 1, 0, 1, 0, 0, 0, 1], [0, 0, 0, 0, 0, 0, 0, 1]]), 116 | 16 117 | ); 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/leetcode/problem/count_binary_substrings.rs: -------------------------------------------------------------------------------- 1 | // 696. Count Binary Substrings, Easy 2 | // https://leetcode.com/problems/count-binary-substrings/ 3 | impl Solution { 4 | pub fn count_binary_substrings(s: String) -> i32 { 5 | let mut chars = s.chars().collect::>(); 6 | chars.push('#'); 7 | let n = s.len(); 8 | if n == 0 { 9 | return 0; 10 | } 11 | 12 | let mut prev = chars[0]; 13 | let mut count = 1; 14 | 15 | let mut counts = vec![]; 16 | for i in 1..n { 17 | if prev == chars[i] { 18 | count += 1; 19 | } else { 20 | counts.push(count); 21 | prev = chars[i]; 22 | count = 1; 23 | } 24 | } 25 | 26 | let mut substrings_count = 0; 27 | for i in 0..counts.len() - 1 { 28 | substrings_count += i32::min(counts[i], counts[i - 1]); 29 | } 30 | 31 | substrings_count 32 | } 33 | } 34 | 35 | struct Solution {} 36 | -------------------------------------------------------------------------------- /src/leetcode/problem/course-schedule.rs: -------------------------------------------------------------------------------- 1 | use std::collections::{HashMap, VecDeque}; 2 | 3 | // 207. Course Schedule, Medium 4 | // https://leetcode.com/problems/course-schedule/ 5 | impl Solution { 6 | pub fn can_finish(num_courses: i32, prerequisites: Vec>) -> bool { 7 | let mut indegree = (0..num_courses).map(|_| 0).collect::>(); 8 | 9 | let mut hm = HashMap::>::new(); 10 | for prereq in prerequisites.iter() { 11 | let [course, pre_course] = [prereq[0], prereq[1]]; 12 | hm.entry(pre_course).and_modify(|f| f.push(course)).or_insert(vec![course]); 13 | indegree[course as usize] += 1; 14 | } 15 | 16 | let mut queue = VecDeque::new(); 17 | for (i, course) in indegree.iter().enumerate() { 18 | if *course == 0 { 19 | queue.push_back(i as i32); 20 | } 21 | } 22 | 23 | let mut count = 0; 24 | while !queue.is_empty() { 25 | let c = queue.pop_front().unwrap(); 26 | count += 1; 27 | 28 | for &v in hm.get(&c).unwrap_or(&vec![]) { 29 | indegree[v as usize] -= 1; 30 | if indegree[v as usize] == 0 { 31 | queue.push_back(v); 32 | } 33 | } 34 | } 35 | 36 | count == num_courses 37 | } 38 | } 39 | 40 | struct Solution {} 41 | 42 | #[cfg(test)] 43 | mod tests { 44 | use super::*; 45 | use crate::vec_vec_i32; 46 | 47 | #[test] 48 | fn test_can_finish() { 49 | assert_eq!(Solution::can_finish(2, vec_vec_i32![[1, 0]]), true); 50 | } 51 | 52 | #[test] 53 | fn test_can_finish2() { 54 | assert_eq!(Solution::can_finish(2, vec_vec_i32![[1, 0], [0, 1]]), false); 55 | } 56 | 57 | #[test] 58 | fn test_can_finish3() { 59 | assert_eq!( 60 | Solution::can_finish(20, vec_vec_i32![[0, 10], [3, 18], [5, 5], [6, 11], [11, 14], [13, 1], [15, 1], [17, 4]]), 61 | false 62 | ); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/leetcode/problem/course-schedule_two.rs: -------------------------------------------------------------------------------- 1 | use std::collections::{HashMap, VecDeque}; 2 | 3 | // 210. Course Schedule II, Medium 4 | // https://leetcode.com/problems/course-schedule-ii/ 5 | impl Solution { 6 | pub fn find_order(num_courses: i32, prerequisites: Vec>) -> Vec { 7 | let mut indegree = (0..num_courses).map(|_| 0).collect::>(); 8 | 9 | let mut hm = HashMap::>::new(); 10 | for prereq in prerequisites.iter() { 11 | let [course, pre_course] = [prereq[0], prereq[1]]; 12 | hm.entry(pre_course).and_modify(|f| f.push(course)).or_insert(vec![course]); 13 | indegree[course as usize] += 1; 14 | } 15 | 16 | let mut queue = VecDeque::new(); 17 | for (i, course) in indegree.iter().enumerate() { 18 | if *course == 0 { 19 | queue.push_back(i as i32); 20 | } 21 | } 22 | 23 | let mut order: Vec = vec![]; 24 | while !queue.is_empty() { 25 | let c = queue.pop_front().unwrap(); 26 | order.push(c); 27 | 28 | for &v in hm.get(&c).unwrap_or(&vec![]) { 29 | indegree[v as usize] -= 1; 30 | if indegree[v as usize] == 0 { 31 | queue.push_back(v); 32 | } 33 | } 34 | } 35 | 36 | if order.len() == num_courses as usize { 37 | order 38 | } else { 39 | vec![] 40 | } 41 | } 42 | } 43 | 44 | struct Solution {} 45 | 46 | #[cfg(test)] 47 | mod tests { 48 | use super::*; 49 | use crate::vec_vec_i32; 50 | 51 | #[test] 52 | fn test_find_order() { 53 | assert_eq!(Solution::find_order(2, vec_vec_i32![[1, 0]]).len(), 2); 54 | } 55 | 56 | #[test] 57 | fn test_find_order2() { 58 | assert_eq!(Solution::find_order(4, vec_vec_i32![[1, 0], [2, 0], [3, 1], [3, 2]]).len(), 4); 59 | } 60 | 61 | #[test] 62 | fn test_find_order3() { 63 | assert_eq!(Solution::find_order(1, vec_vec_i32![]), [0]); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/leetcode/problem/diameter_of_binary_tree.rs: -------------------------------------------------------------------------------- 1 | // Definition for a binary tree node. 2 | #[derive(Debug, PartialEq, Eq)] 3 | pub struct TreeNode { 4 | pub val: i32, 5 | pub left: Option>>, 6 | pub right: Option>>, 7 | } 8 | 9 | impl TreeNode { 10 | #[inline] 11 | pub fn new(val: i32) -> Self { 12 | TreeNode { val, left: None, right: None } 13 | } 14 | } 15 | 16 | use std::cell::RefCell; 17 | use std::rc::Rc; 18 | 19 | // 543. Diameter of Binary Tree, Easy 20 | // https://leetcode.com/problems/diameter-of-binary-tree/ 21 | impl Solution { 22 | pub fn diameter_of_binary_tree(root: Option>>) -> i32 { 23 | fn bfs(node: Option>>, max_path_length: &mut i32) -> i32 { 24 | if node.is_none() { 25 | return 0; 26 | } 27 | let node = node.as_ref().unwrap().borrow(); 28 | 29 | let path_left = bfs(node.left.clone(), max_path_length); 30 | let path_right = bfs(node.right.clone(), max_path_length); 31 | 32 | let path_length = 1 + path_left + path_right; 33 | *max_path_length = i32::max(*max_path_length, path_length); 34 | 35 | 1 + i32::max(path_left, path_right) 36 | } 37 | 38 | let mut max_path_length = 0; 39 | bfs(root, &mut max_path_length); 40 | 41 | max_path_length - 1 42 | } 43 | } 44 | 45 | struct Solution {} 46 | -------------------------------------------------------------------------------- /src/leetcode/problem/dot_product.rs: -------------------------------------------------------------------------------- 1 | // 1570. Dot Product of Two Sparse Vectors, Medium 2 | // https://leetcode.com/problems/dot-product-of-two-sparse-vectors/ 3 | impl SparseVector { 4 | fn new(nums: Vec) -> Self { 5 | SparseVector { nums } 6 | } 7 | 8 | fn dot_product(&self, vec: SparseVector) -> i32 { 9 | let mut result = 0; 10 | 11 | for i in 0..self.nums.len() { 12 | result += self.nums[i] * vec.nums[i]; 13 | } 14 | 15 | result 16 | } 17 | } 18 | 19 | struct SparseVector { 20 | nums: Vec, 21 | } 22 | -------------------------------------------------------------------------------- /src/leetcode/problem/erase_overlap_intervals.rs: -------------------------------------------------------------------------------- 1 | // 435. Non-overlapping Intervals, Medium 2 | // https://leetcode.com/problems/non-overlapping-intervals/ 3 | impl Solution { 4 | pub fn erase_overlap_intervals(mut intervals: Vec>) -> i32 { 5 | intervals.sort_by(|a, b| a[1].cmp(&b[1])); 6 | 7 | let mut rms = 0; 8 | let mut prev = 0; 9 | 10 | for i in 1..intervals.len() { 11 | if intervals[prev][1] > intervals[i][0] { 12 | rms += 1; 13 | } else { 14 | prev = i; 15 | } 16 | } 17 | 18 | rms 19 | } 20 | } 21 | 22 | struct Solution {} 23 | 24 | #[cfg(test)] 25 | mod tests { 26 | use super::*; 27 | use crate::vec_vec_i32; 28 | 29 | #[test] 30 | fn test_erase_overlap_intervals() { 31 | assert_eq!(Solution::erase_overlap_intervals(vec_vec_i32![[1, 2], [2, 3], [3, 4], [1, 3]]), 1); 32 | } 33 | 34 | #[test] 35 | fn test_erase_overlap_intervals2() { 36 | assert_eq!(Solution::erase_overlap_intervals(vec_vec_i32![[1, 2], [1, 2], [1, 2]]), 2); 37 | } 38 | 39 | #[test] 40 | fn test_erase_overlap_intervals3() { 41 | assert_eq!(Solution::erase_overlap_intervals(vec_vec_i32![[1, 2], [2, 3]]), 0); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/leetcode/problem/exist.rs: -------------------------------------------------------------------------------- 1 | use std::collections::{HashSet, VecDeque}; 2 | 3 | impl Solution { 4 | pub fn exist(board: Vec>, word: String) -> bool { 5 | if word.is_empty() { 6 | return true; 7 | } 8 | 9 | let [n, m] = [board.len(), board[0].len()]; 10 | 11 | fn dfs(board: &Vec>, word: &String, idx: i32, pos: (i32, i32), seen: &mut Vec>, ans: &mut bool) { 12 | let [n, m] = [board.len(), board[0].len()]; 13 | let (i, j) = pos; 14 | 15 | if idx >= word.len() as i32 { 16 | *ans = true; 17 | return; 18 | } 19 | 20 | if 0 > i || i >= n as i32 || 0 > j || j >= m as i32 { 21 | return; 22 | } 23 | if seen[i as usize][j as usize] == 1 { 24 | return; 25 | } 26 | if board[i as usize][j as usize] != word.chars().nth(idx as usize).unwrap() { 27 | return; 28 | } 29 | 30 | seen[i as usize][j as usize] = 1; 31 | let dirs = vec![(0, 1), (0, -1), (1, 0), (-1, 0)]; 32 | for dir in dirs.iter() { 33 | let _pos = (i + dir.0, j + dir.1); 34 | dfs(board, word, idx + 1, (i + dir.0, j + dir.1), seen, ans); 35 | } 36 | seen[i as usize][j as usize] = 0; 37 | } 38 | 39 | let mut ans = false; 40 | for i in 0..n { 41 | for j in 0..m { 42 | let [i, j] = [i as i32, j as i32]; 43 | let mut seen = vec![vec![0; m]; n]; 44 | dfs(&board, &word, 0, (i, j), &mut seen, &mut ans); 45 | } 46 | } 47 | 48 | ans 49 | } 50 | } 51 | 52 | struct Solution {} 53 | 54 | #[cfg(test)] 55 | mod tests { 56 | use super::*; 57 | use crate::{vec_vec_char, vec_vec_i32}; 58 | 59 | #[test] 60 | fn test_exist() { 61 | assert_eq!( 62 | Solution::exist(vec_vec_char![['A', 'B', 'C', 'E'], ['S', 'F', 'C', 'S'], ['A', 'D', 'E', 'E']], "ABCCED".to_string()), 63 | true 64 | ); 65 | } 66 | 67 | #[test] 68 | fn test_exist2() { 69 | assert_eq!( 70 | Solution::exist(vec_vec_char![['A', 'B', 'C', 'E'], ['S', 'F', 'C', 'S'], ['A', 'D', 'E', 'E']], "SEE".to_string()), 71 | true 72 | ); 73 | } 74 | 75 | #[test] 76 | fn test_exist3() { 77 | assert_eq!( 78 | Solution::exist(vec_vec_char![['A', 'B', 'C', 'E'], ['S', 'F', 'C', 'S'], ['A', 'D', 'E', 'E']], "ABCB".to_string()), 79 | false 80 | ); 81 | } 82 | 83 | #[test] 84 | fn test_exist4() { 85 | assert_eq!(Solution::exist(vec_vec_char![['a']], "a".to_string()), true); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/leetcode/problem/find_duplicates.rs: -------------------------------------------------------------------------------- 1 | // 442. Find All Duplicates in an Array, Medium 2 | // https://leetcode.com/problems/find-all-duplicates-in-an-array/ 3 | impl Solution { 4 | pub fn find_duplicates(mut nums: Vec) -> Vec { 5 | nums.sort_unstable(); 6 | 7 | let mut ans = vec![]; 8 | let n = nums.len(); 9 | if n == 0 { 10 | return ans; 11 | } 12 | 13 | let mut prev = nums[0]; 14 | 15 | for i in 1..n { 16 | if nums[i] == prev { 17 | ans.push(nums[i]); 18 | } 19 | prev = nums[i]; 20 | } 21 | 22 | ans 23 | } 24 | } 25 | 26 | struct Solution {} 27 | 28 | #[cfg(test)] 29 | mod tests { 30 | use super::*; 31 | 32 | #[test] 33 | fn test_find_duplicates() { 34 | assert_eq!(Solution::find_duplicates(vec![4, 3, 2, 7, 8, 2, 3, 1]), vec![2, 3]); 35 | } 36 | 37 | #[test] 38 | fn test_find_duplicates2() { 39 | assert_eq!(Solution::find_duplicates(vec![1, 1, 2]), vec![1]); 40 | } 41 | 42 | #[test] 43 | fn test_find_duplicates3() { 44 | assert_eq!(Solution::find_duplicates(vec![1]), vec![]); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/leetcode/problem/find_least_num_of_unique_ints.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | // 1481. Least Number of Unique Integers after K Removals, Medium 4 | // https://leetcode.com/problems/least-number-of-unique-integers-after-k-removals/ 5 | impl Solution { 6 | pub fn find_least_num_of_unique_ints(arr: Vec, k: i32) -> i32 { 7 | let mut dict = HashMap::::new(); 8 | 9 | for num in arr.iter() { 10 | dict.entry(*num).and_modify(|n| *n += 1).or_insert(1); 11 | } 12 | 13 | let mut list = dict.keys().map(|k| (*k, dict[k])).collect::>(); 14 | list.sort_unstable_by(|a, b| a.1.cmp(&b.1)); 15 | 16 | let mut k = k; 17 | let mut i = 0; 18 | let mut num_uniques = list.len(); 19 | 20 | while k > 0 { 21 | let can_rm = i32::min(k, list[i].1); 22 | 23 | if list[i].1 - can_rm == 0 { 24 | num_uniques -= 1; 25 | i += 1; 26 | k -= can_rm; 27 | } else { 28 | k -= can_rm; 29 | } 30 | } 31 | 32 | // let list = 33 | 34 | num_uniques as i32 35 | } 36 | } 37 | 38 | struct Solution {} 39 | -------------------------------------------------------------------------------- /src/leetcode/problem/find_min_arrow_shots.rs: -------------------------------------------------------------------------------- 1 | // 452. Minimum Number of Arrows to Burst Balloons, Medium 2 | // https://leetcode.com/problems/minimum-number-of-arrows-to-burst-balloons/ 3 | impl Solution { 4 | pub fn find_min_arrow_shots(mut points: Vec>) -> i32 { 5 | points.sort_by(|a, b| a[1].cmp(&b[1])); 6 | 7 | let mut rms = 1; 8 | let mut prev = 0; 9 | 10 | for i in 1..points.len() { 11 | if points[prev][1] < points[i][0] { 12 | rms += 1; 13 | prev = i; 14 | } 15 | } 16 | 17 | rms 18 | } 19 | } 20 | 21 | struct Solution {} 22 | 23 | #[cfg(test)] 24 | mod tests { 25 | use super::*; 26 | use crate::vec_vec_i32; 27 | 28 | #[test] 29 | fn test_find_min_arrow_shots() { 30 | assert_eq!(Solution::find_min_arrow_shots(vec_vec_i32![[10, 16], [2, 8], [1, 6], [7, 12]]), 2); 31 | } 32 | 33 | #[test] 34 | fn test_find_min_arrow_shots2() { 35 | assert_eq!(Solution::find_min_arrow_shots(vec_vec_i32![[1, 2], [3, 4], [5, 6], [7, 8]]), 4); 36 | } 37 | 38 | #[test] 39 | fn test_find_min_arrow_shots3() { 40 | assert_eq!(Solution::find_min_arrow_shots(vec_vec_i32![[1, 2], [2, 3], [3, 4], [4, 5]]), 2); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/leetcode/problem/find_poisoned_duration.rs: -------------------------------------------------------------------------------- 1 | // 495. Teemo Attacking, Easy 2 | // https://leetcode.com/problems/teemo-attacking/ 3 | impl Solution { 4 | pub fn find_poisoned_duration(time_series: Vec, duration: i32) -> i32 { 5 | let mut sum = 0; 6 | 7 | let mut tick_off = 0; 8 | time_series.iter().for_each(|&t| { 9 | if t > tick_off { 10 | sum += duration; 11 | } else { 12 | sum += duration + (t - tick_off); 13 | } 14 | tick_off = duration + t; 15 | }); 16 | sum 17 | } 18 | } 19 | 20 | struct Solution {} 21 | 22 | #[cfg(test)] 23 | mod tests { 24 | use super::*; 25 | 26 | #[test] 27 | fn test_find_poisoned_duration() { 28 | assert_eq!(Solution::find_poisoned_duration(vec![1, 4], 2), 4); 29 | } 30 | 31 | #[test] 32 | fn test_find_poisoned_duration2() { 33 | assert_eq!(Solution::find_poisoned_duration(vec![1, 2], 2), 3); 34 | } 35 | 36 | #[test] 37 | fn test_find_poisoned_duration3() { 38 | assert_eq!(Solution::find_poisoned_duration(vec![1, 2], 3), 4); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/leetcode/problem/find_words.rs: -------------------------------------------------------------------------------- 1 | use std::{ 2 | collections::{HashMap, HashSet}, 3 | iter::FromIterator, 4 | }; 5 | 6 | // 212. Word Search II, Hard 7 | // https://leetcode.com/problems/word-search-ii/ 8 | impl Solution { 9 | pub fn find_words(board: Vec>, words: Vec) -> Vec { 10 | struct WordTie { 11 | char: char, 12 | is_word: bool, 13 | children: HashMap, 14 | } 15 | 16 | impl WordTie { 17 | fn new(char: char) -> Self { 18 | WordTie { 19 | char, 20 | is_word: false, 21 | children: HashMap::new(), 22 | } 23 | } 24 | } 25 | 26 | let mut word_tie = WordTie::new('/'); 27 | for word in words.iter() { 28 | let mut current = &mut word_tie; 29 | for c in word.chars() { 30 | current.children.entry(c).or_insert(WordTie::new(c)); 31 | current = current.children.get_mut(&c).unwrap(); 32 | } 33 | current.is_word = true; 34 | } 35 | 36 | fn backtracking(board: &mut Vec>, word_tie: &WordTie, ans: &mut HashSet, curr: String, i: i32, j: i32) { 37 | let (n, m) = (board.len() as i32, board[0].len() as i32); 38 | let dirs = vec![(0, 1), (0, -1), (1, 0), (-1, 0)]; 39 | 40 | if word_tie.is_word { 41 | ans.insert(curr.clone()); 42 | } 43 | 44 | for dir in dirs { 45 | let (di, dj) = (i + dir.0, j + dir.1); 46 | if 0 > di || n <= di || 0 > dj || m <= dj { 47 | continue; 48 | } 49 | 50 | let char = board[di as usize][dj as usize]; 51 | 52 | if char == '.' { 53 | continue; 54 | } 55 | 56 | if word_tie.children.contains_key(&char) { 57 | let mut next_curr = curr.clone(); 58 | next_curr.push_str(char.to_string().as_str()); 59 | board[di as usize][dj as usize] = '.'; 60 | backtracking(board, word_tie.children.get(&char).unwrap(), ans, next_curr, di, dj); 61 | board[di as usize][dj as usize] = char; 62 | } 63 | } 64 | } 65 | 66 | let mut ans: HashSet = HashSet::new(); 67 | let mut board = board; 68 | let (n, m) = (board.len(), board[0].len()); 69 | for i in 0..n { 70 | for j in 0..m { 71 | let char = board[i][j]; 72 | if word_tie.children.contains_key(&char) { 73 | board[i][j] = '.'; 74 | backtracking(&mut board, word_tie.children.get(&char).unwrap(), &mut ans, char.to_string(), i as i32, j as i32); 75 | board[i][j] = char; 76 | } 77 | } 78 | } 79 | 80 | Vec::from_iter(ans) 81 | } 82 | } 83 | 84 | struct Solution {} 85 | 86 | #[cfg(test)] 87 | mod tests { 88 | use super::*; 89 | use crate::{vec_string, vec_vec_char}; 90 | 91 | #[test] 92 | fn test_find_words() { 93 | assert_eq!( 94 | Solution::find_words( 95 | vec_vec_char![['o', 'a', 'a', 'n'], ['e', 't', 'a', 'e'], ['i', 'h', 'k', 'r'], ['i', 'f', 'l', 'v']], 96 | vec_string!["oath", "pea", "eat", "rain"] 97 | ) 98 | .len(), 99 | 2 100 | ); 101 | } 102 | 103 | #[test] 104 | fn test_find_words2() { 105 | assert_eq!(Solution::find_words(vec_vec_char![['a', 'b'], ['c', 'd']], vec_string!["abcb"]), vec_string![]); 106 | } 107 | 108 | #[test] 109 | fn test_find_words3() { 110 | assert_eq!(Solution::find_words(vec_vec_char![['a']], vec_string!["a"]), vec_string!["a"]); 111 | } 112 | 113 | #[test] 114 | fn test_find_words4() { 115 | assert_eq!( 116 | Solution::find_words( 117 | vec_vec_char![['o', 'a', 'b', 'n'], ['o', 't', 'a', 'e'], ['a', 'h', 'k', 'r'], ['a', 'f', 'l', 'v']], 118 | vec_string!["oa", "oaa"] 119 | ) 120 | .len(), 121 | 2 122 | ); 123 | } 124 | 125 | #[test] 126 | fn test_find_words5() { 127 | assert_eq!(Solution::find_words(vec_vec_char![['a', 'a']], vec_string!["aaa"]), vec_string![]); 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /src/leetcode/problem/get_number_of_backlog_orders.rs: -------------------------------------------------------------------------------- 1 | use std::collections::BinaryHeap; 2 | 3 | // 1801. Number of Orders in the Backlog, Medium 4 | // https://leetcode.com/problems/number-of-orders-in-the-backlog/ 5 | impl Solution { 6 | pub fn get_number_of_backlog_orders(orders: Vec>) -> i32 { 7 | #[derive(Eq, Debug, Clone)] 8 | struct Order { 9 | price: i32, 10 | amount: i32, 11 | order_type: i32, 12 | } 13 | 14 | impl Order { 15 | fn new(mut price: i32, amount: i32, order_type: i32) -> Self { 16 | if order_type == 1 { 17 | price *= -1; 18 | } 19 | 20 | Self { price, amount, order_type } 21 | } 22 | } 23 | 24 | impl Ord for Order { 25 | fn cmp(&self, other: &Self) -> std::cmp::Ordering { 26 | self.price.cmp(&other.price) 27 | } 28 | } 29 | 30 | impl PartialOrd for Order { 31 | fn partial_cmp(&self, other: &Self) -> Option { 32 | Some(self.cmp(other)) 33 | } 34 | } 35 | 36 | impl PartialEq for Order { 37 | fn eq(&self, other: &Self) -> bool { 38 | self.price == other.price 39 | } 40 | } 41 | 42 | let base: i32 = 10; 43 | let modulo: f64 = (base.pow(9) + 7) as f64; 44 | 45 | let mut buy_backlog: BinaryHeap = BinaryHeap::new(); 46 | let mut sell_backlog: BinaryHeap = BinaryHeap::new(); 47 | 48 | for order in orders.iter() { 49 | let mut o = Order::new(order[0], order[1], order[2]); 50 | 51 | while o.amount > 0 { 52 | if o.order_type == 0 { 53 | if !sell_backlog.is_empty() && sell_backlog.peek().unwrap().price * -1 <= o.price { 54 | let mut sell_order = sell_backlog.pop().unwrap(); 55 | let amount = i32::min(sell_order.amount, o.amount); 56 | o.amount -= amount; 57 | sell_order.amount -= amount; 58 | 59 | if sell_order.amount > 0 { 60 | sell_backlog.push(sell_order); 61 | } 62 | } else { 63 | buy_backlog.push(o.clone()); 64 | break; 65 | } 66 | } else if !buy_backlog.is_empty() && buy_backlog.peek().unwrap().price >= o.price * -1 { 67 | let mut buy_order = buy_backlog.pop().unwrap(); 68 | let amount = i32::min(buy_order.amount, o.amount); 69 | o.amount -= amount; 70 | buy_order.amount -= amount; 71 | 72 | if buy_order.amount > 0 { 73 | buy_backlog.push(buy_order); 74 | } 75 | } else { 76 | sell_backlog.push(o.clone()); 77 | break; 78 | } 79 | } 80 | } 81 | 82 | ((buy_backlog.iter().map(|order| order.amount as f64).sum::() + sell_backlog.iter().map(|order| order.amount as f64).sum::()) % modulo) as i32 83 | } 84 | } 85 | 86 | struct Solution {} 87 | 88 | #[cfg(test)] 89 | mod tests { 90 | use super::*; 91 | use crate::vec_vec_i32; 92 | 93 | #[test] 94 | fn test_get_number_of_backlog_orders() { 95 | assert_eq!(Solution::get_number_of_backlog_orders(vec_vec_i32![[10, 5, 0], [15, 2, 1], [25, 1, 1], [30, 4, 0]]), 6); 96 | } 97 | 98 | #[test] 99 | fn test_get_number_of_backlog_orders2() { 100 | assert_eq!( 101 | Solution::get_number_of_backlog_orders(vec_vec_i32![[7, 1000000000, 1], [15, 3, 0], [5, 999999995, 0], [5, 1, 1]]), 102 | 999999984 103 | ); 104 | } 105 | 106 | #[test] 107 | fn test_get_number_of_backlog_orders3() { 108 | assert_eq!(Solution::get_number_of_backlog_orders(vec_vec_i32![[19, 28, 0], [9, 4, 1], [25, 15, 1]]), 39); 109 | } 110 | 111 | #[test] 112 | fn test_get_number_of_backlog_orders4() { 113 | assert_eq!( 114 | Solution::get_number_of_backlog_orders(vec_vec_i32![ 115 | [944925198, 885003661, 0], 116 | [852263791, 981056352, 0], 117 | [16300530, 415829909, 0], 118 | [940927944, 713835606, 0], 119 | [606389372, 407474168, 1], 120 | [139563740, 85382287, 1], 121 | [700244880, 901922025, 1], 122 | [972900669, 15506445, 0], 123 | [576578542, 65339074, 0], 124 | [45972021, 293765308, 0], 125 | [464403992, 97750995, 0], 126 | [29659852, 536508041, 0], 127 | [799523481, 299864737, 0], 128 | [711908211, 480514887, 1], 129 | [354125407, 677598767, 1], 130 | [279004011, 688916331, 0], 131 | [263524013, 64622178, 0], 132 | [375395974, 460070320, 0], 133 | [971786816, 379275200, 1], 134 | [577774472, 214070125, 1], 135 | [987757349, 711231195, 0] 136 | ]), 137 | 83062672 138 | ); 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /src/leetcode/problem/guess_number.rs: -------------------------------------------------------------------------------- 1 | // 374. Guess Number Higher or Lower, Easy 2 | // https://leetcode.com/problems/guess-number-higher-or-lower/ 3 | impl Solution { 4 | // fn provided by leetcode 5 | unsafe fn guess(_n: i32) -> i32 { 6 | 1 7 | } 8 | 9 | unsafe fn guess_umber(n: i32) -> i32 { 10 | let mut l = 0; 11 | let mut r = n; 12 | 13 | while l < r { 14 | let mid = l + (r - l) / 2; 15 | 16 | match Solution::guess(mid) { 17 | -1 => { 18 | r = mid - 1; 19 | } 20 | 1 => { 21 | l = mid + 1; 22 | } 23 | 0 => { 24 | return mid; 25 | } 26 | _ => unreachable!(), 27 | } 28 | } 29 | 30 | l 31 | } 32 | } 33 | 34 | struct Solution {} 35 | -------------------------------------------------------------------------------- /src/leetcode/problem/implement_trie_prefix_tree.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | // 208. Implement Trie (Prefix Tree), Medium 4 | // https://leetcode.com/problems/implement-trie-prefix-tree/ 5 | struct CharNode { 6 | char: char, 7 | is_word: bool, 8 | children: HashMap, 9 | } 10 | 11 | impl Trie { 12 | fn new() -> Self { 13 | Trie { 14 | root: CharNode { 15 | char: '*', 16 | is_word: false, 17 | children: HashMap::new(), 18 | }, 19 | } 20 | } 21 | 22 | fn insert(&mut self, word: String) { 23 | let mut current = &mut self.root; 24 | for c in word.chars() { 25 | current.children.entry(c).or_insert(CharNode { 26 | char: c, 27 | is_word: false, 28 | children: HashMap::new(), 29 | }); 30 | current = current.children.get_mut(&c).unwrap(); 31 | } 32 | current.is_word = true; 33 | } 34 | 35 | fn search(&self, word: String) -> bool { 36 | let mut current = &self.root; 37 | for c in word.chars() { 38 | if !current.children.contains_key(&c) { 39 | return false; 40 | } 41 | current = current.children.get(&c).unwrap(); 42 | } 43 | 44 | current.is_word 45 | } 46 | 47 | fn starts_with(&self, prefix: String) -> bool { 48 | let mut current = &self.root; 49 | for c in prefix.chars() { 50 | if !current.children.contains_key(&c) { 51 | return false; 52 | } 53 | current = current.children.get(&c).unwrap(); 54 | } 55 | true 56 | } 57 | } 58 | 59 | struct Trie { 60 | root: CharNode, 61 | } 62 | 63 | #[cfg(test)] 64 | mod tests { 65 | use super::*; 66 | 67 | #[test] 68 | fn test_trie() { 69 | let mut obj = Trie::new(); 70 | obj.insert("Martin".to_string()); 71 | 72 | let ret_2: bool = obj.search("Martin".to_string()); 73 | assert_eq!(ret_2, true); 74 | 75 | let ret_3: bool = obj.starts_with("Mar".to_string()); 76 | assert_eq!(ret_3, true); 77 | 78 | let ret_4: bool = obj.starts_with("Mara".to_string()); 79 | assert_eq!(ret_4, false); 80 | 81 | let ret_5: bool = obj.search("Mar".to_string()); 82 | assert_eq!(ret_5, false); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/leetcode/problem/inorder_traversal.rs: -------------------------------------------------------------------------------- 1 | #[derive(Debug, PartialEq, Eq)] 2 | pub struct TreeNode { 3 | pub val: i32, 4 | pub left: Option>>, 5 | pub right: Option>>, 6 | } 7 | 8 | impl TreeNode { 9 | #[inline] 10 | pub fn new(val: i32) -> Self { 11 | TreeNode { val, left: None, right: None } 12 | } 13 | } 14 | 15 | use std::cell::RefCell; 16 | use std::collections::VecDeque; 17 | use std::rc::Rc; 18 | 19 | // 94. Binary Tree Inorder Traversal, Easy 20 | // https://leetcode.com/problems/binary-tree-inorder-traversal/ 21 | impl Solution { 22 | pub fn inorder_traversal(root: Option>>) -> Vec { 23 | let mut ans = vec![]; 24 | 25 | fn bfs(node: Option>>, ans: &mut Vec) { 26 | if let Some(node) = node { 27 | bfs(node.borrow().left.clone(), ans); 28 | ans.push(node.borrow().val); 29 | bfs(node.borrow().right.clone(), ans); 30 | } 31 | } 32 | 33 | bfs(root, &mut ans); 34 | 35 | ans 36 | } 37 | } 38 | 39 | struct Solution {} 40 | -------------------------------------------------------------------------------- /src/leetcode/problem/interval_intersection.rs: -------------------------------------------------------------------------------- 1 | // 986. Interval List Intersections, Medium 2 | // https://leetcode.com/problems/interval-list-intersections/ 3 | impl Solution { 4 | pub fn interval_intersection(first_list: Vec>, second_list: Vec>) -> Vec> { 5 | let mut ans: Vec> = vec![]; 6 | 7 | let (mut i, mut j) = (0, 0); 8 | 9 | while i < first_list.len() && j < second_list.len() { 10 | let start = i32::max(first_list[i][0], second_list[j][0]); 11 | let end = i32::min(first_list[i][1], second_list[j][1]); 12 | 13 | if start <= end { 14 | ans.push(vec![start, end]); 15 | } 16 | 17 | if first_list[i][1] < second_list[j][1] { 18 | i += 1; 19 | } else { 20 | j += 1; 21 | } 22 | } 23 | 24 | ans 25 | } 26 | } 27 | 28 | struct Solution {} 29 | -------------------------------------------------------------------------------- /src/leetcode/problem/is_anagram.rs: -------------------------------------------------------------------------------- 1 | // 242. Valid Anagram, Easy 2 | // https://leetcode.com/problems/valid-anagram/ 3 | impl Solution { 4 | pub fn is_anagram(s: String, t: String) -> bool { 5 | if s.len() != t.len() { 6 | return false; 7 | } 8 | 9 | let mut s_chars: Vec = s.chars().collect(); 10 | let mut t_chars: Vec = t.chars().collect(); 11 | s_chars.sort_unstable(); 12 | t_chars.sort_unstable(); 13 | 14 | for i in 0..s_chars.len() { 15 | if (s_chars[i] as u8) != (t_chars[i] as u8) { 16 | return false; 17 | } 18 | } 19 | 20 | true 21 | } 22 | } 23 | 24 | struct Solution {} 25 | 26 | #[cfg(test)] 27 | mod tests { 28 | use super::*; 29 | 30 | #[test] 31 | fn test_is_anagram() { 32 | assert_eq!(Solution::is_anagram("anagram".to_string(), "nagaram".to_string()), true); 33 | } 34 | 35 | #[test] 36 | fn test_is_anagram2() { 37 | assert_eq!(Solution::is_anagram("rat".to_string(), "car".to_string()), false); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/leetcode/problem/is_cousins.rs: -------------------------------------------------------------------------------- 1 | #[derive(Debug, PartialEq, Eq)] 2 | pub struct TreeNode { 3 | pub val: i32, 4 | pub left: Option>>, 5 | pub right: Option>>, 6 | } 7 | 8 | impl TreeNode { 9 | #[inline] 10 | pub fn new(val: i32) -> Self { 11 | TreeNode { val, left: None, right: None } 12 | } 13 | } 14 | 15 | use std::cell::RefCell; 16 | use std::rc::Rc; 17 | 18 | // 993. Cousins in Binary Tree, Easy 19 | // https://leetcode.com/problems/cousins-in-binary-tree/ 20 | impl Solution { 21 | pub fn is_cousins(root: Option>>, x: i32, y: i32) -> bool { 22 | let mut found: Vec<(i32, i32)> = vec![]; // (parent, level) 23 | 24 | fn bfs(node: Option>>, x: &i32, y: &i32, parent: i32, level: i32, found: &mut Vec<(i32, i32)>) { 25 | if node.is_some() { 26 | let node = node.as_ref().unwrap().borrow(); 27 | 28 | if found.len() == 2 { 29 | return; 30 | } 31 | 32 | if node.val == *x || node.val == *y { 33 | found.push((parent, level)); 34 | return; 35 | } 36 | 37 | bfs(node.left.clone(), &x, &y, node.val, level + 1, found); 38 | bfs(node.right.clone(), &x, &y, node.val, level + 1, found); 39 | } 40 | } 41 | 42 | bfs(root, &x, &y, -1, 0, &mut found); 43 | 44 | found.len() == 2 && found[0].0 != found[1].0 && found[0].1 == found[1].1 45 | } 46 | } 47 | 48 | struct Solution {} 49 | -------------------------------------------------------------------------------- /src/leetcode/problem/is_good_array.rs: -------------------------------------------------------------------------------- 1 | // 1134. Armstrong Number, Easy 2 | // https://leetcode.com/problems/armstrong-number/ 3 | impl Solution { 4 | pub fn is_armstrong(n: i32) -> bool { 5 | let mut digits = vec![]; 6 | let mut tmp = n; 7 | while tmp > 0 { 8 | digits.push(tmp % 10); 9 | tmp /= 10; 10 | } 11 | 12 | let mut sum = 0; 13 | for digit in digits.iter() { 14 | sum += digit.pow(digits.len() as u32); 15 | } 16 | 17 | sum == n 18 | } 19 | } 20 | 21 | struct Solution {} 22 | 23 | #[cfg(test)] 24 | mod tests { 25 | use super::*; 26 | 27 | #[test] 28 | fn test_is_armstrong() { 29 | assert_eq!(Solution::is_armstrong(153), true); 30 | } 31 | 32 | #[test] 33 | fn test_is_armstrong2() { 34 | assert_eq!(Solution::is_armstrong(123), false); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/leetcode/problem/is_same_tree.rs: -------------------------------------------------------------------------------- 1 | #[derive(Debug, PartialEq, Eq)] 2 | pub struct TreeNode { 3 | pub val: i32, 4 | pub left: Option>>, 5 | pub right: Option>>, 6 | } 7 | 8 | impl TreeNode { 9 | #[inline] 10 | pub fn new(val: i32) -> Self { 11 | TreeNode { val, left: None, right: None } 12 | } 13 | } 14 | use std::cell::RefCell; 15 | use std::rc::Rc; 16 | 17 | // 100. Same Tree, Easy 18 | // https://leetcode.com/problems/same-tree/ 19 | impl Solution { 20 | pub fn is_same_tree(p: Option>>, q: Option>>) -> bool { 21 | fn bfs(node1: Option>>, node2: Option>>) -> bool { 22 | if let (Some(node1), Some(node2)) = (node1.clone(), node2.clone()) { 23 | if node1.borrow().val != node2.borrow().val { 24 | return false; 25 | } 26 | 27 | return bfs(node1.borrow().left.clone(), node2.borrow().left.clone()) && bfs(node1.borrow().right.clone(), node2.borrow().right.clone()); 28 | } else { node1.is_none() && node2.is_none() } 29 | } 30 | 31 | bfs(p, q) 32 | } 33 | } 34 | 35 | struct Solution {} 36 | -------------------------------------------------------------------------------- /src/leetcode/problem/island_perimeter.rs: -------------------------------------------------------------------------------- 1 | // 463. Island Perimeter, Easy 2 | // https://leetcode.com/problems/island-perimeter/ 3 | impl Solution { 4 | pub fn island_perimeter(mut grid: Vec>) -> i32 { 5 | let mut size = 0; 6 | 7 | fn bfs(grid: &mut Vec>, i: i32, j: i32, size: &mut i32) { 8 | if i < 0 || j < 0 || i >= grid.len() as i32 || j >= grid[0].len() as i32 || grid[i as usize][j as usize] == 0 { 9 | *size += 1; 10 | return; 11 | } else if grid[i as usize][j as usize] == 2 { 12 | return; 13 | } 14 | 15 | grid[i as usize][j as usize] = 2; 16 | 17 | bfs(grid, i + 1, j, size); 18 | bfs(grid, i, j + 1, size); 19 | bfs(grid, i - 1, j, size); 20 | bfs(grid, i, j - 1, size); 21 | } 22 | 23 | 'outer: for i in 0..grid.len() { 24 | for j in 0..grid[0].len() { 25 | if grid[i][j] == 1 { 26 | bfs(&mut grid, i as i32, j as i32, &mut size); 27 | break 'outer; 28 | } 29 | } 30 | } 31 | 32 | size 33 | } 34 | } 35 | 36 | struct Solution {} 37 | 38 | #[cfg(test)] 39 | mod tests { 40 | use super::*; 41 | use crate::vec_vec_i32; 42 | 43 | #[test] 44 | fn test_island_perimeter() { 45 | assert_eq!(Solution::island_perimeter(vec_vec_i32![[0, 1, 0, 0], [1, 1, 1, 0], [0, 1, 0, 0], [1, 1, 0, 0]]), 16); 46 | } 47 | 48 | #[test] 49 | fn test_island_perimeter2() { 50 | assert_eq!(Solution::island_perimeter(vec_vec_i32![[1]]), 4); 51 | } 52 | 53 | #[test] 54 | fn test_island_perimeter3() { 55 | assert_eq!(Solution::island_perimeter(vec_vec_i32![[1, 0]]), 4); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/leetcode/problem/k_closest.rs: -------------------------------------------------------------------------------- 1 | use std::cmp::Ordering; 2 | 3 | // 973. K Closest Points to Origin, Medium 4 | // https://leetcode.com/problems/k-closest-points-to-origin/ 5 | impl Solution { 6 | pub fn k_closest(points: Vec>, k: i32) -> Vec> { 7 | let mut enhanced_points = points 8 | .iter() 9 | .map(|n| { 10 | let dist = f64::sqrt(f64::powi(n[0] as f64, 2) + f64::powi(n[1] as f64, 2)); 11 | (n[0], n[1], dist) 12 | }) 13 | .collect::>(); 14 | enhanced_points.sort_unstable_by(|a, b| a.2.partial_cmp(&b.2).unwrap_or(Ordering::Equal)); 15 | 16 | enhanced_points.iter().take(k as usize).map(|n| vec![n.0, n.1]).collect() 17 | } 18 | } 19 | 20 | struct Solution {} 21 | -------------------------------------------------------------------------------- /src/leetcode/problem/kth_smallest.rs: -------------------------------------------------------------------------------- 1 | pub struct TreeNode { 2 | pub val: i32, 3 | pub left: Option>>, 4 | pub right: Option>>, 5 | } 6 | 7 | impl TreeNode { 8 | #[inline] 9 | pub fn new(val: i32) -> Self { 10 | TreeNode { val, left: None, right: None } 11 | } 12 | } 13 | 14 | use std::cell::RefCell; 15 | use std::rc::Rc; 16 | 17 | // 230. Kth Smallest Element in a BST, Medium 18 | // https://leetcode.com/problems/kth-smallest-element-in-a-bst/ 19 | impl Solution { 20 | pub fn kth_smallest(root: Option>>, k: i32) -> i32 { 21 | fn bfs(node: Option>>, k: i32, c: &mut i32, target: &mut i32) { 22 | if let Some(node) = node { 23 | bfs(node.borrow().left.clone(), k, c, target); 24 | *c += 1; 25 | if *c == k { 26 | *target = node.borrow().val; 27 | return; 28 | } 29 | bfs(node.borrow().right.clone(), k, c, target); 30 | } 31 | } 32 | 33 | let mut c = 0; 34 | let mut target = -1; 35 | bfs(root, k, &mut c, &mut target); 36 | 37 | target 38 | } 39 | } 40 | 41 | struct Solution {} 42 | -------------------------------------------------------------------------------- /src/leetcode/problem/largest_divisible_subset.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | // 368. Largest Divisible Subset, Medium 4 | // https://leetcode.com/problems/largest-divisible-subset/ 5 | impl Solution { 6 | pub fn largest_divisible_subset(mut nums: Vec) -> Vec { 7 | if nums.is_empty() { 8 | return vec![]; 9 | } 10 | 11 | nums.sort_unstable(); 12 | 13 | let mut sol = vec![]; 14 | for i in 0..nums.len() { 15 | sol.push(vec![nums[i]]); 16 | } 17 | 18 | for i in 0..nums.len() { 19 | for j in 0..i { 20 | if nums[i] % nums[j] == 0 && sol[i].len() < sol[j].len() + 1 { 21 | let mut append = sol[j].clone(); 22 | append.push(nums[i]); 23 | sol[i] = append; 24 | } 25 | } 26 | } 27 | 28 | sol.sort_by_key(|a| a.len()); 29 | 30 | return sol.last().unwrap().to_vec(); 31 | } 32 | } 33 | 34 | struct Solution {} 35 | 36 | #[cfg(test)] 37 | mod tests { 38 | use super::*; 39 | 40 | #[test] 41 | fn test_largest_divisible_subset() { 42 | assert_eq!(Solution::largest_divisible_subset(vec![1, 2, 3]), vec![1, 3]); 43 | } 44 | 45 | #[test] 46 | fn test_largest_divisible_subset2() { 47 | assert_eq!(Solution::largest_divisible_subset(vec![1, 2, 4, 8]), vec![1, 2, 4, 8]); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/leetcode/problem/left_most_column_with_one.rs: -------------------------------------------------------------------------------- 1 | #[derive(Copy, Clone)] 2 | struct BinaryMatrix; 3 | 4 | #[allow(unused_variables)] 5 | impl BinaryMatrix { 6 | fn get(self, row: i32, col: i32) -> i32 { 7 | 1 8 | } 9 | 10 | fn dimensions(self) -> Vec { 11 | vec![] 12 | } 13 | } 14 | 15 | // 1428. Leftmost Column with at Least a One, Medium 16 | // https://leetcode.com/problems/leftmost-column-with-at-least-a-one/ 17 | impl Solution { 18 | pub fn left_most_column_with_one(binary_matrix: &BinaryMatrix) -> i32 { 19 | let dim: Vec<_> = binary_matrix.dimensions(); 20 | 21 | let mut row = dim[0] - 1; 22 | let mut col = dim[1] - 1; 23 | 24 | let mut candidate: Option = None; 25 | 26 | while row >= 0 && col >= 0 { 27 | if binary_matrix.get(row, col) == 1 { 28 | candidate = Some(col); 29 | col -= 1; 30 | } else { 31 | row -= 1; 32 | } 33 | } 34 | 35 | candidate.unwrap_or(-1) 36 | } 37 | } 38 | 39 | struct Solution {} 40 | -------------------------------------------------------------------------------- /src/leetcode/problem/longest_palindrome_subseq.rs: -------------------------------------------------------------------------------- 1 | // 516. Longest Palindromic Subsequence, Medium 2 | // https://leetcode.com/problems/longest-palindromic-subsequence/ 3 | impl Solution { 4 | pub fn longest_palindrome_subseq(s: String) -> i32 { 5 | let n = s.len(); 6 | let mut dp = vec![vec![0; n]; n]; 7 | 8 | let chars = s.chars().collect::>(); 9 | 10 | for i in 0..n { 11 | dp[i][i] = 1; 12 | } 13 | 14 | for i in 1..n { 15 | for j in 0..s.len() - i { 16 | let i = j + i; 17 | if chars[j] == chars[i] { 18 | dp[j][i] = 2 + dp[j + 1][i - 1]; 19 | } else { 20 | dp[j][i] = i32::max(dp[j + 1][i], dp[j][i - 1]); 21 | } 22 | } 23 | } 24 | 25 | dp[0][n - 1] 26 | } 27 | } 28 | 29 | struct Solution {} 30 | 31 | #[cfg(test)] 32 | mod tests { 33 | use super::*; 34 | use crate::{vec_vec_char, vec_vec_i32}; 35 | 36 | #[test] 37 | fn test_longest_palindrome_subseq() { 38 | assert_eq!(Solution::longest_palindrome_subseq("bbbab".to_string()), 4); 39 | } 40 | 41 | #[test] 42 | fn test_longest_palindrome_subseq2() { 43 | assert_eq!(Solution::longest_palindrome_subseq("cbbd".to_string()), 2); 44 | } 45 | 46 | #[test] 47 | fn test_longest_palindrome_subseq3() { 48 | assert_eq!(Solution::longest_palindrome_subseq("cbbd".to_string()), 2); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/leetcode/problem/max_area_of_island.rs: -------------------------------------------------------------------------------- 1 | // 695. Max Area of Island, Medium 2 | // https://leetcode.com/problems/max-area-of-island/ 3 | impl Solution { 4 | pub fn max_area_of_island(grid: Vec>) -> i32 { 5 | let [n, m] = [grid.len(), grid[0].len()]; 6 | 7 | fn bfs(grid: &mut Vec>, pos: (i32, i32)) -> i32 { 8 | let [n, m] = [grid.len() as i32, grid[0].len() as i32]; 9 | 10 | if pos.0 < 0 || pos.0 >= n || pos.1 < 0 || pos.1 >= m { 11 | return 0; 12 | } 13 | 14 | if grid[pos.0 as usize][pos.1 as usize] == 0 { 15 | return 0; 16 | } 17 | 18 | grid[pos.0 as usize][pos.1 as usize] = 0; 19 | 20 | let mut size = 1; 21 | 22 | let dirs = vec![(0, 1), (0, -1), (1, 0), (-1, 0)]; 23 | for dir in dirs.iter() { 24 | let new_pos = (pos.0 + dir.0, pos.1 + dir.1); 25 | size += bfs(grid, new_pos); 26 | } 27 | 28 | size 29 | } 30 | 31 | let mut grid = grid; 32 | let mut biggest_island_size = 0; 33 | 34 | for i in 0..n { 35 | for j in 0..m { 36 | if grid[i][j] == 1 { 37 | let island_size = bfs(&mut grid, (i as i32, j as i32)); 38 | biggest_island_size = i32::max(biggest_island_size, island_size); 39 | } 40 | } 41 | } 42 | 43 | biggest_island_size 44 | } 45 | } 46 | 47 | struct Solution {} 48 | -------------------------------------------------------------------------------- /src/leetcode/problem/max_level_sum.rs: -------------------------------------------------------------------------------- 1 | #[derive(Debug, PartialEq, Eq)] 2 | pub struct TreeNode { 3 | pub val: i32, 4 | pub left: Option>>, 5 | pub right: Option>>, 6 | } 7 | 8 | impl TreeNode { 9 | #[inline] 10 | pub fn new(val: i32) -> Self { 11 | TreeNode { val, left: None, right: None } 12 | } 13 | } 14 | 15 | use std::cell::RefCell; 16 | use std::collections::HashMap; 17 | use std::rc::Rc; 18 | 19 | // 1161. Maximum Level Sum of a Binary Tree, Medium 20 | // https://leetcode.com/problems/maximum-level-sum-of-a-binary-tree/ 21 | impl Solution { 22 | pub fn max_level_sum(root: Option>>) -> i32 { 23 | let mut level_sum = HashMap::::new(); 24 | 25 | fn bfs(node: Option>>, level: i32, level_sum: &mut HashMap) { 26 | if node.is_some() { 27 | let node = node.as_ref().unwrap().borrow(); 28 | 29 | level_sum.entry(level).and_modify(|e| *e += node.val).or_insert(node.val); 30 | 31 | bfs(node.left.clone(), level + 1, level_sum); 32 | bfs(node.right.clone(), level + 1, level_sum); 33 | } 34 | } 35 | 36 | bfs(root, 1, &mut level_sum); 37 | 38 | let max_value = *level_sum.iter().max_by(|x, y| x.1.cmp(y.1)).unwrap().1; 39 | *level_sum.iter().filter(|x| x.1 == &max_value).map(|x| x.0).min().unwrap() 40 | } 41 | } 42 | 43 | struct Solution {} 44 | -------------------------------------------------------------------------------- /src/leetcode/problem/max_profit.rs: -------------------------------------------------------------------------------- 1 | // 309. Best Time to Buy and Sell Stock with Cooldown, Medium 2 | // https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-cooldown/ 3 | impl Solution { 4 | pub fn max_profit(prices: Vec) -> i32 { 5 | let n = prices.len(); 6 | if n < 2 { 7 | return 0; 8 | } 9 | 10 | let [mut sold, mut held, mut reset] = [i32::MIN, i32::MIN, 0]; 11 | 12 | for price in prices.iter() { 13 | let pre_sold = sold; 14 | sold = held + price; 15 | held = i32::max(held, reset - price); 16 | reset = i32::max(reset, pre_sold) 17 | } 18 | 19 | i32::max(sold, reset) 20 | } 21 | } 22 | 23 | struct Solution {} 24 | -------------------------------------------------------------------------------- /src/leetcode/problem/max_profit2.rs: -------------------------------------------------------------------------------- 1 | // 123. Best Time to Buy and Sell Stock III, Hard 2 | // https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iii/ 3 | impl Solution { 4 | pub fn max_profit(prices: Vec) -> i32 { 5 | let n = prices.len(); 6 | if n < 2 { 7 | return 0; 8 | } 9 | 10 | let [mut t1_cost, mut t2_cost] = [i32::MAX, i32::MAX]; 11 | let [mut t1_profit, mut t2_profit] = [0, 0]; 12 | 13 | for &price in prices.iter() { 14 | t1_cost = i32::min(t1_cost, price); 15 | t1_profit = i32::max(t1_profit, price - t1_cost); 16 | t2_cost = i32::min(t2_cost, price - t1_profit); 17 | t2_profit = i32::max(t2_profit, price - t2_cost); 18 | } 19 | 20 | t2_profit 21 | } 22 | } 23 | 24 | struct Solution {} 25 | -------------------------------------------------------------------------------- /src/leetcode/problem/max_uncrossed_lines.rs: -------------------------------------------------------------------------------- 1 | // 1035. Uncrossed Lines, Medium 2 | // https://leetcode.com/problems/uncrossed-lines/ 3 | impl Solution { 4 | pub fn max_uncrossed_lines(nums1: Vec, nums2: Vec) -> i32 { 5 | let [n, m] = [nums1.len(), nums2.len()]; 6 | let mut dp = vec![vec![0; m + 1]; n + 1]; 7 | 8 | for i in 1..n + 1 { 9 | for j in 1..m + 1 { 10 | if nums1[i - 1] == nums2[j - 1] { 11 | dp[i][j] = i32::min(dp[i - 1][j], i32::min(dp[i][j - 1], dp[i - 1][j - 1])) + 1 12 | } else { 13 | dp[i][j] = i32::max(dp[i - 1][j], i32::max(dp[i][j - 1], dp[i - 1][j - 1])); 14 | } 15 | } 16 | } 17 | 18 | dp[n][m] 19 | } 20 | } 21 | 22 | struct Solution {} 23 | 24 | #[cfg(test)] 25 | mod tests { 26 | use super::*; 27 | use crate::vec_vec_i32; 28 | 29 | #[test] 30 | fn test_max_uncrossed_lines() { 31 | assert_eq!(Solution::max_uncrossed_lines(vec![1, 4, 2], vec![1, 2, 4]), 2); 32 | } 33 | 34 | #[test] 35 | fn test_max_uncrossed_lines2() { 36 | assert_eq!(Solution::max_uncrossed_lines(vec![2, 5, 1, 2, 5], vec![10, 5, 2, 1, 5, 2]), 3); 37 | } 38 | 39 | #[test] 40 | fn test_max_uncrossed_lines3() { 41 | assert_eq!(Solution::max_uncrossed_lines(vec![1, 3, 7, 1, 7, 5], vec![1, 9, 2, 5, 1]), 2); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/leetcode/problem/merge.rs: -------------------------------------------------------------------------------- 1 | // 56. Merge Intervals, Medium 2 | // https://leetcode.com/problems/merge-intervals/ 3 | impl Solution { 4 | pub fn merge(intervals: Vec>) -> Vec> { 5 | let mut intervals = intervals; 6 | intervals.sort_unstable_by(|a, b| a[0].cmp(&b[0])); 7 | let mut ans: Vec> = vec![]; 8 | 9 | for interval in intervals.iter_mut() { 10 | if ans.is_empty() { 11 | ans.push(interval.clone()); 12 | } else if interval[0] >= ans.last().unwrap()[0] && interval[1] <= ans.last().unwrap()[1] { 13 | continue; 14 | } else if interval[0] <= ans.last().unwrap()[1] { 15 | ans.last_mut().unwrap()[1] = interval[1]; 16 | } else { 17 | ans.push(interval.clone()); 18 | } 19 | } 20 | 21 | ans 22 | } 23 | } 24 | 25 | struct Solution {} 26 | 27 | mod tests { 28 | use super::*; 29 | use crate::{vec_string, vec_vec_i32}; 30 | 31 | #[test] 32 | fn test_merge() { 33 | assert_eq!(Solution::merge(vec_vec_i32![[1, 3], [2, 6], [8, 10], [15, 18]]), vec_vec_i32![[1, 6], [8, 10], [15, 18]]); 34 | } 35 | 36 | #[test] 37 | fn test_merge2() { 38 | assert_eq!(Solution::merge(vec_vec_i32![[1, 4], [4, 5]]), vec_vec_i32![[1, 5]]); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/leetcode/problem/min_area.rs: -------------------------------------------------------------------------------- 1 | // 302. Smallest Rectangle Enclosing Black Pixels, Hard 2 | // https://leetcode.com/problems/smallest-rectangle-enclosing-black-pixels/ 3 | impl Solution { 4 | pub fn min_area(image: Vec>, x: i32, y: i32) -> i32 { 5 | let [mut min_x, mut max_x, mut min_y, mut max_y] = [i32::MAX, i32::MIN, i32::MAX, i32::MIN]; 6 | 7 | fn bfs(image: &mut Vec>, x: i32, y: i32, min_x: &mut i32, max_x: &mut i32, min_y: &mut i32, max_y: &mut i32) { 8 | let [n, m] = [image.len() as i32, image[0].len() as i32]; 9 | 10 | if x < 0 || x >= n || y < 0 || y >= m { 11 | return; 12 | } 13 | 14 | let directions = vec![(0, 1), (0, -1), (1, 0), (-1, 0)]; 15 | 16 | if image[x as usize][y as usize] == '1' { 17 | *min_x = i32::min(*min_x, x); 18 | *max_x = i32::max(*max_x, x); 19 | *min_y = i32::min(*min_y, y); 20 | *max_y = i32::max(*max_y, y); 21 | 22 | image[x as usize][y as usize] = '0'; 23 | 24 | for &(dx, dy) in directions.iter() { 25 | bfs(image, x + dx, y + dy, min_x, max_x, min_y, max_y); 26 | } 27 | } 28 | } 29 | 30 | let mut image = image; 31 | bfs(&mut image, x, y, &mut min_x, &mut max_x, &mut min_y, &mut max_y); 32 | 33 | (max_x - min_x + 1) * (max_y - min_y + 1) as i32 34 | } 35 | } 36 | 37 | struct Solution {} 38 | 39 | #[cfg(test)] 40 | mod tests { 41 | use super::*; 42 | use crate::vec_vec_char; 43 | 44 | #[test] 45 | fn test_island_perimeter() { 46 | assert_eq!(Solution::min_area(vec_vec_char![['0', '0', '1', '0'], ['0', '1', '1', '0'], ['0', '1', '0', '0']], 0, 2), 6); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/leetcode/problem/min_distance.rs: -------------------------------------------------------------------------------- 1 | // 72. Edit Distance, Hard 2 | // https://leetcode.com/problems/edit-distance/ 3 | impl Solution { 4 | pub fn min_distance(word1: String, word2: String) -> i32 { 5 | let [n, m] = [word1.len(), word2.len()]; 6 | let mut dp = vec![vec![0; m + 1]; n + 1]; 7 | 8 | for i in 0..n + 1 { 9 | dp[i][0] = i as i32; 10 | } 11 | for j in 0..m + 1 { 12 | dp[0][j] = j as i32; 13 | } 14 | 15 | for i in 1..n + 1 { 16 | for j in 1..m + 1 { 17 | if word1.chars().nth(i - 1) == word2.chars().nth(j - 1) { 18 | dp[i][j] = dp[i - 1][j - 1] 19 | } else { 20 | dp[i][j] = i32::min(dp[i - 1][j], i32::min(dp[i][j - 1], dp[i - 1][j - 1])) + 1; 21 | } 22 | } 23 | } 24 | 25 | dp[n][m] 26 | } 27 | } 28 | 29 | struct Solution {} 30 | 31 | #[cfg(test)] 32 | mod tests { 33 | use super::*; 34 | use crate::vec_vec_i32; 35 | 36 | #[test] 37 | fn test_min_distance() { 38 | assert_eq!(Solution::min_distance("horse".to_string(), "ros".to_string()), 3); 39 | } 40 | 41 | #[test] 42 | fn test_min_distance2() { 43 | assert_eq!(Solution::min_distance("intention".to_string(), "execution".to_string()), 5); 44 | } 45 | 46 | #[test] 47 | fn test_min_distance3() { 48 | assert_eq!(Solution::min_distance("".to_string(), "a".to_string()), 1); 49 | } 50 | 51 | #[test] 52 | fn test_min_distance4() { 53 | assert_eq!(Solution::min_distance("b".to_string(), "".to_string()), 1); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/leetcode/problem/min_eating_speed.rs: -------------------------------------------------------------------------------- 1 | // 875. Koko Eating Bananas, Medium 2 | // https://leetcode.com/problems/koko-eating-bananas/ 3 | impl Solution { 4 | pub fn min_eating_speed(piles: Vec, h: i32) -> i32 { 5 | if piles.is_empty() { 6 | return 0; 7 | } 8 | 9 | let [mut lo, mut hi] = [0, i32::max_value()]; 10 | 11 | fn can_eat(piles: &Vec, h: i32, k: i32) -> bool { 12 | let mut hours = 0; 13 | piles.iter().for_each(|p| { 14 | hours += f64::ceil(*p as f64 / k as f64) as i32; 15 | }); 16 | hours <= h 17 | } 18 | 19 | while hi - lo > 1 { 20 | let mid = lo + (hi - lo) / 2; 21 | if can_eat(&piles, h, mid) { 22 | hi = mid; 23 | } else { 24 | lo = mid; 25 | } 26 | } 27 | 28 | hi 29 | } 30 | } 31 | 32 | struct Solution {} 33 | 34 | #[cfg(test)] 35 | mod tests { 36 | use super::*; 37 | 38 | #[test] 39 | fn test_min_eating_speed() { 40 | assert_eq!(Solution::min_eating_speed(vec![3, 6, 7, 11], 8), 4); 41 | } 42 | 43 | #[test] 44 | fn test_min_eating_speed2() { 45 | assert_eq!(Solution::min_eating_speed(vec![3], 3), 1); 46 | } 47 | 48 | #[test] 49 | fn test_min_eating_speed3() { 50 | assert_eq!(Solution::min_eating_speed(vec![], 3), 0); 51 | } 52 | 53 | #[test] 54 | fn test_min_eating_speed4() { 55 | assert_eq!( 56 | Solution::min_eating_speed( 57 | vec![ 58 | 332484035, 524908576, 855865114, 632922376, 222257295, 690155293, 112677673, 679580077, 337406589, 290818316, 877337160, 901728858, 679284947, 688210097, 59 | 692137887, 718203285, 629455728, 941802184 60 | ], 61 | 823855818 62 | ), 63 | 14 64 | ); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/leetcode/problem/min_knight_moves.rs: -------------------------------------------------------------------------------- 1 | use std::collections::{HashSet, VecDeque}; 2 | 3 | // 1197. Minimum Knight Moves, Medium 4 | // https://leetcode.com/problems/minimum-knight-moves/ 5 | impl Solution { 6 | pub fn min_knight_moves(x: i32, y: i32) -> i32 { 7 | let mut queue = VecDeque::new(); 8 | queue.push_back(((0, 0), 0)); 9 | 10 | let mut seen = HashSet::<(i32, i32)>::new(); 11 | 12 | let knight_moves = vec![(1, 2), (2, 1), (2, -1), (1, -2), (-1, -2), (-2, -1), (-2, 1), (-1, 2)]; 13 | 14 | while !queue.is_empty() { 15 | let (pos, moves) = queue.pop_front().unwrap(); 16 | 17 | if x == pos.0 && y == pos.1 { 18 | return moves; 19 | } 20 | 21 | for knight_move in &knight_moves { 22 | let new_pos = (pos.0 + knight_move.0, pos.1 + knight_move.1); 23 | if !seen.contains(&new_pos) { 24 | seen.insert(new_pos); 25 | queue.push_back((new_pos, moves + 1)); 26 | } 27 | } 28 | } 29 | 30 | -1 31 | } 32 | } 33 | 34 | struct Solution {} 35 | -------------------------------------------------------------------------------- /src/leetcode/problem/min_meeting_rooms.rs: -------------------------------------------------------------------------------- 1 | use std::collections::BinaryHeap; 2 | 3 | // 253. Meeting Rooms II, Medium 4 | // https://leetcode.com/problems/meeting-rooms-ii/ 5 | impl Solution { 6 | pub fn min_meeting_rooms(intervals: Vec>) -> i32 { 7 | let mut intervals = intervals; 8 | intervals.sort_unstable_by(|a, b| a[0].cmp(&b[0])); 9 | 10 | let mut rooms = 0; 11 | let mut heap = BinaryHeap::new(); 12 | 13 | for interval in intervals.iter() { 14 | if heap.is_empty() { 15 | heap.push(interval[1]); 16 | rooms += 1; 17 | } else if heap.peek().unwrap() <= &interval[0] { 18 | heap.pop(); 19 | heap.push(interval[1]); 20 | } else { 21 | heap.push(interval[1]); 22 | rooms += 1; 23 | } 24 | } 25 | 26 | rooms 27 | } 28 | } 29 | 30 | struct Solution {} 31 | -------------------------------------------------------------------------------- /src/leetcode/problem/min_stone_sum.rs: -------------------------------------------------------------------------------- 1 | use std::collections::BinaryHeap; 2 | 3 | // 1962. Remove Stones to Minimize the Total, Medium 4 | // https://leetcode.com/problems/remove-stones-to-minimize-the-total/ 5 | impl Solution { 6 | pub fn min_stone_sum(piles: Vec, k: i32) -> i32 { 7 | let mut heap = BinaryHeap::from(piles); 8 | 9 | for _ in 0..k { 10 | let mut t = heap.pop().unwrap_or(0); 11 | t -= f32::floor(t as f32 / 2.0) as i32; 12 | heap.push(t); 13 | } 14 | 15 | heap.iter().sum() 16 | } 17 | } 18 | 19 | struct Solution {} 20 | 21 | #[cfg(test)] 22 | mod tests { 23 | use super::*; 24 | use crate::vec_vec_i32; 25 | 26 | #[test] 27 | fn test_min_stone_sum() { 28 | assert_eq!(Solution::min_stone_sum(vec![5, 4, 9], 2), 12); 29 | } 30 | 31 | #[test] 32 | fn test_min_stone_sum2() { 33 | assert_eq!(Solution::min_stone_sum(vec![4, 3, 6, 7], 3), 12); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/leetcode/problem/min_transfers.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | // 465. Optimal Account Balancing, Hard 4 | // https://leetcode.com/problems/optimal-account-balancing/ 5 | impl Solution { 6 | pub fn min_transfers(transactions: Vec>) -> i32 { 7 | let mut hm = HashMap::new(); 8 | 9 | for transaction in transactions.iter() { 10 | let (from, to, amount) = (transaction[0], transaction[1], transaction[2]); 11 | hm.entry(from).and_modify(|d| *d -= amount).or_insert(-amount); 12 | hm.entry(to).and_modify(|d| *d += amount).or_insert(amount); 13 | } 14 | 15 | let mut debts = vec![]; 16 | for v in hm.values() { 17 | debts.push(*v); 18 | } 19 | 20 | fn dfs(debts: &mut Vec, mut i: usize) -> i32 { 21 | while i < debts.len() && debts[i] == 0 { 22 | i += 1; 23 | } 24 | 25 | let mut ans = i32::MAX; 26 | let mut prev = 0; 27 | for j in i + 1..debts.len() { 28 | if debts[j] != prev && debts[j] * debts[i] < 0 { 29 | debts[j] += debts[i]; 30 | ans = i32::min(ans, 1 + dfs(debts, i + 1)); 31 | debts[j] -= debts[i]; 32 | prev = debts[j]; 33 | } 34 | } 35 | 36 | if ans < i32::MAX { 37 | ans 38 | } else { 39 | 0 40 | } 41 | } 42 | 43 | dfs(&mut debts, 0) 44 | } 45 | } 46 | 47 | struct Solution {} 48 | -------------------------------------------------------------------------------- /src/leetcode/problem/mod.rs: -------------------------------------------------------------------------------- 1 | automod::dir!("src/leetcode/problem"); -------------------------------------------------------------------------------- /src/leetcode/problem/next_greater_element.rs: -------------------------------------------------------------------------------- 1 | use std::collections::{HashMap, VecDeque}; 2 | 3 | // 496. Next Greater Element I, Easy 4 | // https://leetcode.com/problems/next-greater-element-i/ 5 | impl Solution { 6 | pub fn next_greater_element(nums1: Vec, nums2: Vec) -> Vec { 7 | let mut queue = VecDeque::new(); 8 | let mut nums2_next_bigger = HashMap::new(); 9 | 10 | for (i, curr_num) in nums2.iter().enumerate() { 11 | while queue.len() > 0 && *queue.back().unwrap() < curr_num { 12 | let num = queue.pop_back().unwrap(); 13 | nums2_next_bigger.insert(num, *curr_num); 14 | } 15 | queue.push_back(curr_num); 16 | } 17 | 18 | queue.iter().for_each(|k| { 19 | nums2_next_bigger.insert(*k, -1); 20 | }); 21 | 22 | let mut ans = vec![]; 23 | 24 | 'outer: for i in 0..nums1.len() { 25 | for j in 0..nums2.len() { 26 | if nums1[i] == nums2[j] { 27 | ans.push(*nums2_next_bigger.get(&nums2[j]).unwrap()); 28 | continue 'outer; 29 | } 30 | } 31 | } 32 | 33 | ans 34 | } 35 | 36 | pub fn next_greater_element_slow(nums1: Vec, nums2: Vec) -> Vec { 37 | let mut ans = vec![]; 38 | 39 | 'outer: for i in 0..nums1.len() { 40 | let mut found = -1; 41 | let mut found_i = -1; 42 | 43 | for j in i + 1..nums2.len() { 44 | if nums1[i] == nums2[j] { 45 | found = nums2[j]; 46 | found_i = j as i32; 47 | break; 48 | } 49 | } 50 | 51 | if found_i != -1 { 52 | let found_i = found_i as usize; 53 | for i in found_i + 1..nums2.len() { 54 | if found < nums2[i] { 55 | ans.push(nums2[i]); 56 | continue 'outer; 57 | } 58 | } 59 | } 60 | 61 | ans.push(-1); 62 | } 63 | 64 | ans 65 | } 66 | } 67 | 68 | struct Solution {} 69 | -------------------------------------------------------------------------------- /src/leetcode/problem/next_permutation.rs: -------------------------------------------------------------------------------- 1 | // 31. Next Permutation, Medium 2 | // https://leetcode.com/problems/next-permutation/ 3 | impl Solution { 4 | pub fn next_permutation(nums: &mut Vec) { 5 | let n = nums.len(); 6 | 7 | if n <= 1 { 8 | return; 9 | } 10 | 11 | let mut swapped_at = 0; 12 | 'outer: for l in (0..n).rev() { 13 | for r in (0..n).rev() { 14 | if r > l && nums[r] > nums[l] { 15 | nums.swap(l, r); 16 | swapped_at = l + 1; 17 | break 'outer; 18 | } 19 | } 20 | } 21 | 22 | let mut i = swapped_at; 23 | while i < n - 1 { 24 | if nums[i] > nums[i + 1] { 25 | nums.swap(i, i + 1); 26 | i = swapped_at; 27 | continue; 28 | } 29 | i += 1; 30 | } 31 | } 32 | } 33 | 34 | struct Solution {} 35 | 36 | #[cfg(test)] 37 | mod tests { 38 | use super::*; 39 | use crate::vec_vec_i32; 40 | 41 | #[test] 42 | fn test_next_permutation() { 43 | let mut nums = vec![1, 2, 3]; 44 | Solution::next_permutation(&mut nums); 45 | assert_eq!(nums, vec![1, 3, 2]); 46 | } 47 | 48 | #[test] 49 | fn test_next_permutation2() { 50 | let mut nums = vec![3, 2, 1]; 51 | Solution::next_permutation(&mut nums); 52 | assert_eq!(nums, vec![1, 2, 3]); 53 | } 54 | 55 | #[test] 56 | fn test_next_permutation3() { 57 | let mut nums = vec![1, 1, 5]; 58 | Solution::next_permutation(&mut nums); 59 | assert_eq!(nums, vec![1, 5, 1]); 60 | } 61 | 62 | #[test] 63 | fn test_next_permutation4() { 64 | let mut nums = vec![1]; 65 | Solution::next_permutation(&mut nums); 66 | assert_eq!(nums, vec![1]); 67 | } 68 | 69 | #[test] 70 | fn test_next_permutation5() { 71 | let mut nums = vec![1, 3, 2]; 72 | Solution::next_permutation(&mut nums); 73 | assert_eq!(nums, vec![2, 1, 3]); 74 | } 75 | 76 | #[test] 77 | fn test_next_permutation6() { 78 | let mut nums = vec![4, 2, 0, 2, 3, 2, 0]; 79 | Solution::next_permutation(&mut nums); 80 | assert_eq!(nums, vec![4, 2, 0, 3, 0, 2, 2]); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/leetcode/problem/num_islands.rs: -------------------------------------------------------------------------------- 1 | // 200. Number of Islands, Medium 2 | // https://leetcode.com/problems/number-of-islands/ 3 | impl Solution { 4 | pub fn num_islands(mut grid: Vec>) -> i32 { 5 | let [n, m] = [grid.len(), grid[0].len()]; 6 | 7 | fn bfs(grid: &mut Vec>, pos: (i32, i32)) { 8 | grid[pos.0 as usize][pos.1 as usize] = '2'; 9 | 10 | let directions = vec![(0, 1), (0, -1), (1, 0), (-1, 0)]; 11 | for direction in directions.iter() { 12 | let next_pos = (pos.0 + direction.0, pos.1 + direction.1); 13 | 14 | if next_pos.0 < 0 || next_pos.1 < 0 || next_pos.0 >= grid.len() as i32 || next_pos.1 >= grid[0].len() as i32 { 15 | continue; 16 | } 17 | 18 | if grid[next_pos.0 as usize][next_pos.1 as usize] == '1' { 19 | bfs(grid, next_pos); 20 | } 21 | } 22 | } 23 | 24 | let mut islands = 0; 25 | for i in 0..n { 26 | for j in 0..m { 27 | if grid[i][j] == '1' { 28 | islands += 1; 29 | bfs(&mut grid, (i as i32, j as i32)); 30 | } 31 | } 32 | } 33 | 34 | islands 35 | } 36 | } 37 | 38 | struct Solution {} 39 | 40 | #[cfg(test)] 41 | mod tests { 42 | use super::*; 43 | use crate::{vec_string, vec_vec_char}; 44 | 45 | #[test] 46 | fn test_num_islands() { 47 | assert_eq!( 48 | Solution::num_islands(vec_vec_char![ 49 | ['1', '1', '1', '1', '0'], 50 | ['1', '1', '0', '1', '0'], 51 | ['1', '1', '0', '0', '0'], 52 | ['0', '0', '0', '0', '0'] 53 | ]), 54 | 1 55 | ); 56 | } 57 | 58 | #[test] 59 | fn test_num_islands2() { 60 | assert_eq!( 61 | Solution::num_islands(vec_vec_char![ 62 | ['1', '1', '0', '0', '0'], 63 | ['1', '1', '0', '0', '0'], 64 | ['0', '0', '1', '0', '0'], 65 | ['0', '0', '0', '1', '1'] 66 | ]), 67 | 3 68 | ); 69 | } 70 | 71 | #[test] 72 | fn test_num_islands3() { 73 | assert_eq!(Solution::num_islands(vec_vec_char![['1'], ['1']]), 1); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/leetcode/problem/num_of_subarrays.rs: -------------------------------------------------------------------------------- 1 | // @leetup=custom 2 | // @leetup=info id=1524 lang=rust slug=number-of-sub-arrays-with-odd-sum 3 | 4 | /* 5 | * Given an array of integers `arr`, return *the number of subarrays with an 6 | * odd sum*. 7 | * 8 | * Since the answer can be very large, return it modulo `109 + 7`. 9 | * 10 | * 11 | * Example 1: 12 | * 13 | * Input: arr = [1,3,5] 14 | * Output: 4 15 | * Explanation: All subarrays are [[1],[1,3],[1,3,5],[3],[3,5],[5]] 16 | * All sub-arrays sum are [1,4,9,3,8,5]. 17 | * Odd sums are [1,9,3,5] so the answer is 4. 18 | * 19 | * Example 2: 20 | * 21 | * Input: arr = [2,4,6] 22 | * Output: 0 23 | * Explanation: All subarrays are [[2],[2,4],[2,4,6],[4],[4,6],[6]] 24 | * All sub-arrays sum are [2,6,12,4,10,6]. 25 | * All sub-arrays have even sum and the answer is 0. 26 | * 27 | * Example 3: 28 | * 29 | * Input: arr = [1,2,3,4,5,6,7] 30 | * Output: 16 31 | * 32 | * 33 | * Constraints: 34 | * 35 | * * `1 <= arr.length <= 105` 36 | * * `1 <= arr[i] <= 100` 37 | * 38 | */ 39 | // @leetup=custom 40 | // @leetup=code 41 | 42 | impl Solution { 43 | pub fn num_of_subarrays(arr: Vec) -> i32 { 44 | const MOD: i32 = 1_000_000_007; 45 | 46 | let [mut even, mut odd] = [1, 0]; 47 | let mut sum = 0; 48 | let mut ans = 0; 49 | for num in arr.iter() { 50 | sum += num; 51 | 52 | if sum % 2 == 0 { 53 | even += 1; 54 | ans += odd % MOD 55 | } else { 56 | odd += 1; 57 | ans += even % MOD 58 | } 59 | } 60 | 61 | ans 62 | } 63 | } 64 | 65 | struct Solution {} 66 | 67 | #[cfg(test)] 68 | mod tests { 69 | use super::*; 70 | use crate::{vec_string, vec_vec_char}; 71 | 72 | #[test] 73 | fn test_num_of_subarrays() { 74 | assert_eq!(Solution::num_of_subarrays(vec![1, 3, 5]), 4); 75 | } 76 | 77 | #[test] 78 | fn test_num_of_subarrays2() { 79 | assert_eq!(Solution::num_of_subarrays(vec![2, 4, 6]), 0); 80 | } 81 | 82 | #[test] 83 | fn test_num_of_subarrays3() { 84 | assert_eq!(Solution::num_of_subarrays(vec![1, 2, 3, 4, 5, 6, 7]), 16); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/leetcode/problem/num_subarray_product_less_than_k.rs: -------------------------------------------------------------------------------- 1 | // 713. Subarray Product Less Than K, Medium 2 | // https://leetcode.com/problems/subarray-product-less-than-k/ 3 | impl Solution { 4 | pub fn num_subarray_product_less_than_k(nums: Vec, k: i32) -> i32 { 5 | let mut l: i32 = 0; 6 | let mut ans: i32 = 0; 7 | let mut product: i32 = 1; 8 | 9 | for r in 0..nums.len() { 10 | product *= nums[r]; 11 | 12 | if product >= k { 13 | while product >= k && l <= r as i32 { 14 | product /= nums[l as usize]; 15 | l += 1; 16 | } 17 | } 18 | 19 | ans += r as i32 - l as i32 + 1; 20 | } 21 | 22 | ans as i32 23 | } 24 | } 25 | 26 | struct Solution {} 27 | 28 | #[cfg(test)] 29 | mod tests { 30 | use super::*; 31 | 32 | #[test] 33 | fn num_subarray_product_less_than_k() { 34 | assert_eq!(Solution::num_subarray_product_less_than_k(vec![10, 5, 2, 6], 100), 8); 35 | } 36 | 37 | #[test] 38 | fn num_subarray_product_less_than_k2() { 39 | assert_eq!(Solution::num_subarray_product_less_than_k(vec![1, 2, 3], 0), 0); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/leetcode/problem/num_subarrays_with_sum.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | // 930. Binary Subarrays With Sum, Medium 4 | // https://leetcode.com/problems/binary-subarrays-with-sum/ 5 | impl Solution { 6 | pub fn num_subarrays_with_sum(nums: Vec, goal: i32) -> i32 { 7 | let mut ans = 0; 8 | let mut prefix_sum = 0; 9 | let mut prefix_sum_map = HashMap::new(); 10 | for num in nums { 11 | prefix_sum += num; 12 | if prefix_sum == goal { 13 | ans += 1; 14 | } 15 | if let Some(count) = prefix_sum_map.get(&(prefix_sum - goal)) { 16 | ans += *count; 17 | } 18 | 19 | prefix_sum_map.entry(prefix_sum).and_modify(|e| *e += 1).or_insert(1); 20 | } 21 | 22 | ans 23 | } 24 | } 25 | 26 | struct Solution {} 27 | 28 | #[cfg(test)] 29 | mod tests { 30 | use super::*; 31 | 32 | #[test] 33 | fn test_find_duplicates() { 34 | assert_eq!(Solution::num_subarrays_with_sum(vec![1, 0, 1, 0, 1], 2), 4); 35 | } 36 | 37 | #[test] 38 | fn test_find_duplicates2() { 39 | assert_eq!(Solution::num_subarrays_with_sum(vec![0, 0, 0, 0, 0], 0), 15); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/leetcode/problem/order_of_largest_plus_sign.rs: -------------------------------------------------------------------------------- 1 | // 764. Largest Plus Sign, Medium 2 | // https://leetcode.com/problems/largest-plus-sign/ 3 | impl Solution { 4 | pub fn order_of_largest_plus_sign(n: i32, mines: Vec>) -> i32 { 5 | let n = n as usize; 6 | let mut grid = vec![vec![0; n]; n]; 7 | 8 | for mine in mines.iter() { 9 | grid[mine[0] as usize][mine[1] as usize] = 1; 10 | } 11 | 12 | let mut prefix_sum_grid = vec![vec![i32::MAX; n]; n]; 13 | 14 | for i in 0..n { 15 | let mut sum_right = 0; 16 | let mut sum_left = 0; 17 | let mut sum_down = 0; 18 | let mut sum_up = 0; 19 | 20 | for j in 0..n { 21 | sum_right += grid[i][j]; 22 | prefix_sum_grid[i][j] += i32::min(prefix_sum_grid[i][j], sum_right); 23 | 24 | sum_left += grid[i][n - j - 1]; 25 | prefix_sum_grid[i][n - j - 1] += i32::min(prefix_sum_grid[i][n - j - 1], sum_left); 26 | 27 | sum_down += grid[j][i]; 28 | prefix_sum_grid[j][i] += i32::min(prefix_sum_grid[j][i], sum_down); 29 | 30 | sum_up += grid[n - j - 1][i]; 31 | prefix_sum_grid[n - j - 1][i] += i32::min(prefix_sum_grid[n - j - 1][i], sum_up); 32 | } 33 | } 34 | 35 | let mut ans = 0; 36 | for i in 0..n { 37 | for j in 0..n { 38 | ans = i32::max(ans, prefix_sum_grid[i][j]); 39 | } 40 | } 41 | 42 | ans 43 | } 44 | } 45 | 46 | struct Solution {} 47 | -------------------------------------------------------------------------------- /src/leetcode/problem/path_sum_3.rs: -------------------------------------------------------------------------------- 1 | // Definition for a binary tree node. 2 | #[derive(Debug, PartialEq, Eq)] 3 | pub struct TreeNode { 4 | pub val: i32, 5 | pub left: Option>>, 6 | pub right: Option>>, 7 | } 8 | 9 | impl TreeNode { 10 | #[inline] 11 | pub fn new(val: i32) -> Self { 12 | TreeNode { val, left: None, right: None } 13 | } 14 | } 15 | 16 | use std::cell::RefCell; 17 | use std::rc::Rc; 18 | 19 | // 437. Path Sum III, Medium 20 | // https://leetcode.com/problems/path-sum-iii/ 21 | impl Solution { 22 | pub fn path_sum(root: Option>>, target_sum: i32) -> i32 { 23 | fn bfs(node: Option>>, sums: Vec, target_sum: i32, res: &mut i32) { 24 | if let Some(node) = node { 25 | let node = node.borrow_mut(); 26 | let mut new_sums = Vec::new(); 27 | new_sums.push(node.val); 28 | for sum in sums { 29 | new_sums.push(sum + node.val); 30 | if sum + node.val == target_sum { 31 | *res += 1; 32 | } 33 | } 34 | if node.val == target_sum { 35 | *res += 1; 36 | } 37 | 38 | bfs(node.left.clone(), new_sums.clone(), target_sum, res); 39 | bfs(node.right.clone(), new_sums.clone(), target_sum, res); 40 | } 41 | } 42 | 43 | let mut res = 0; 44 | bfs(root, vec![], target_sum, &mut res); 45 | res 46 | } 47 | } 48 | 49 | struct Solution {} 50 | -------------------------------------------------------------------------------- /src/leetcode/problem/perfect_squares.rs: -------------------------------------------------------------------------------- 1 | // 279. Perfect Squares, Medium 2 | // https://leetcode.com/problems/perfect-squares/ 3 | impl Solution { 4 | pub fn num_squares(n: i32) -> i32 { 5 | let mut dp = vec![0; n as usize + 1]; 6 | for i in 1..=n as usize { 7 | let mut min = i as i32; 8 | let mut j = 1; 9 | while j * j <= i { 10 | min = std::cmp::min(min, dp[i - j * j] + 1); 11 | j += 1; 12 | } 13 | dp[i] = min; 14 | } 15 | dp[n as usize] 16 | } 17 | } 18 | 19 | struct Solution {} 20 | -------------------------------------------------------------------------------- /src/leetcode/problem/pseudo_palindromic_paths.rs: -------------------------------------------------------------------------------- 1 | use std::cell::RefCell; 2 | use std::rc::Rc; 3 | 4 | // Definition for a binary tree node. 5 | #[derive(Debug, PartialEq, Eq)] 6 | pub struct TreeNode { 7 | pub val: i32, 8 | pub left: Option>>, 9 | pub right: Option>>, 10 | } 11 | 12 | impl TreeNode { 13 | #[inline] 14 | pub fn new(val: i32) -> Self { 15 | TreeNode { val, left: None, right: None } 16 | } 17 | } 18 | 19 | // 1457. Pseudo-Palindromic Paths in a Binary Tree, Easy 20 | // https://leetcode.com/problems/pseudo-palindromic-paths-in-a-binary-tree/ 21 | impl Solution { 22 | pub fn pseudo_palindromic_paths(root: Option>>) -> i32 { 23 | let mut ans = 0; 24 | 25 | fn dfs(ans: &mut i32, node: Option>>, mut mask: i32) { 26 | if node.is_none() { 27 | return; 28 | } 29 | 30 | let node = node.as_ref().unwrap().borrow(); 31 | 32 | mask ^= 1 << (node.val - 1); 33 | if node.left.is_none() && node.right.is_none() { 34 | if mask == mask & -mask { 35 | *ans += 1; 36 | } 37 | } else { 38 | dfs(ans, node.left.clone(), mask); 39 | dfs(ans, node.right.clone(), mask); 40 | } 41 | } 42 | 43 | dfs(&mut ans, root, 0); 44 | 45 | ans 46 | } 47 | } 48 | 49 | struct Solution {} 50 | -------------------------------------------------------------------------------- /src/leetcode/problem/range_bitwise_and.rs: -------------------------------------------------------------------------------- 1 | // 201. Bitwise AND of Numbers Range, Medium 2 | // https://leetcode.com/problems/bitwise-and-of-numbers-range/ 3 | impl Solution { 4 | pub fn range_bitwise_and(left: i32, right: i32) -> i32 { 5 | let [mut left, mut right] = [left, right]; 6 | let mut shifts = 0; 7 | 8 | while left < right { 9 | left >>= 1; 10 | right >>= 1; 11 | shifts += 1; 12 | } 13 | 14 | left << shifts 15 | } 16 | 17 | pub fn range_bitwise_and_slow(left: i32, right: i32) -> i32 { 18 | let mut ans = left; 19 | 20 | if left < right { 21 | ((left + 1)..=right).for_each(|num| { 22 | println!("{:?}", num); 23 | ans &= num; 24 | }); 25 | } 26 | 27 | ans 28 | } 29 | } 30 | 31 | struct Solution {} 32 | 33 | #[cfg(test)] 34 | mod tests { 35 | use super::*; 36 | 37 | #[test] 38 | fn test_range_bitwise_and() { 39 | assert_eq!(Solution::range_bitwise_and(5, 7), 4); 40 | } 41 | 42 | #[test] 43 | fn test_range_bitwise_and2() { 44 | assert_eq!(Solution::range_bitwise_and(2147483647, 2147483647), 2147483647); 45 | } 46 | 47 | #[test] 48 | fn test_range_bitwise_and3() { 49 | assert_eq!(Solution::range_bitwise_and(1, 2), 0); 50 | } 51 | 52 | #[test] 53 | fn test_range_bitwise_and_slow() { 54 | assert_eq!(Solution::range_bitwise_and(5, 7), 4); 55 | } 56 | 57 | #[test] 58 | fn test_range_bitwise_and_slow2() { 59 | assert_eq!(Solution::range_bitwise_and(2147483647, 2147483647), 2147483647); 60 | } 61 | 62 | #[test] 63 | fn test_range_bitwise_and_slow3() { 64 | assert_eq!(Solution::range_bitwise_and(1, 2), 0); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/leetcode/problem/restore_array.rs: -------------------------------------------------------------------------------- 1 | use std::collections::{HashMap, HashSet}; 2 | 3 | // 1743. Restore the Array From Adjacent Pairs, Medium 4 | // https://leetcode.com/problems/restore-the-array-from-adjacent-pairs/ 5 | impl Solution { 6 | pub fn restore_array(adjacent_pairs: Vec>) -> Vec { 7 | let mut graph: HashMap> = HashMap::new(); 8 | 9 | for pair in adjacent_pairs.iter() { 10 | let (u, v) = (pair[0], pair[1]); 11 | graph.entry(u).and_modify(|e| e.push(v)).or_insert(vec![v]); 12 | graph.entry(v).and_modify(|e| e.push(u)).or_insert(vec![u]); 13 | } 14 | 15 | let n = adjacent_pairs.len() + 1; 16 | let mut ans = vec![]; 17 | 18 | let mut head_cands = graph.iter().map(|(k, v)| (*k, v.len())).collect::>(); 19 | head_cands.sort_by_key(|(_, v)| *v); 20 | 21 | let mut head = head_cands.first().unwrap().0; 22 | let mut seen = HashSet::::new(); 23 | 24 | while ans.len() < n { 25 | seen.insert(head); 26 | ans.push(head); 27 | 28 | let cands = graph.get(&head).unwrap(); 29 | for cand in cands.iter() { 30 | if !seen.contains(&cand) { 31 | seen.insert(*cand); 32 | head = *cand; 33 | break; 34 | } 35 | } 36 | } 37 | 38 | ans 39 | } 40 | } 41 | 42 | struct Solution {} 43 | -------------------------------------------------------------------------------- /src/leetcode/problem/restore_ip_addresses.rs: -------------------------------------------------------------------------------- 1 | // 93. Restore IP Addresses, Medium 2 | // https://leetcode.com/problems/restore-ip-addresses/ 3 | impl Solution { 4 | pub fn restore_ip_addresses(s: String) -> Vec { 5 | let digits = s.chars().map(|c| c.to_digit(10).unwrap()).collect::>(); 6 | 7 | fn helper(blocks: Vec>, digits: &Vec, i: usize, ans: &mut Vec) { 8 | if blocks.len() > 4 || i > digits.len() { 9 | 10 | } else if blocks.len() == 4 && i == digits.len() { 11 | let mut s = String::new(); 12 | for block in blocks { 13 | for d in block { 14 | s.push_str(&d.to_string()); 15 | } 16 | s.push('.'); 17 | } 18 | s.pop(); 19 | ans.push(s); 20 | } else { 21 | let mut block = vec![]; 22 | let mut num = 0; 23 | for j in i..usize::min(digits.len(), i + 3) { 24 | block.push(digits[j]); 25 | num = num * 10 + digits[j]; 26 | if num > 255 || (block.first().unwrap() == &0 && block.len() > 1) { 27 | break; 28 | } 29 | 30 | let mut b = blocks.clone(); 31 | b.push(block.clone()); 32 | helper(b, digits, j + 1, ans); 33 | } 34 | } 35 | } 36 | 37 | let mut ans: Vec = vec![]; 38 | helper(vec![], &digits, 0, &mut ans); 39 | ans 40 | } 41 | } 42 | 43 | struct Solution {} 44 | -------------------------------------------------------------------------------- /src/leetcode/problem/rob.rs: -------------------------------------------------------------------------------- 1 | // Definition for a binary tree node. 2 | #[derive(Debug, PartialEq, Eq)] 3 | pub struct TreeNode { 4 | pub val: i32, 5 | pub left: Option>>, 6 | pub right: Option>>, 7 | } 8 | 9 | impl TreeNode { 10 | #[inline] 11 | pub fn new(val: i32) -> Self { 12 | TreeNode { val, left: None, right: None } 13 | } 14 | } 15 | 16 | use std::cell::RefCell; 17 | use std::rc::Rc; 18 | 19 | // 337. House Robber III, Medium 20 | // https://leetcode.com/problems/house-robber-iii/ 21 | impl Solution { 22 | pub fn rob(root: Option>>) -> i32 { 23 | fn bfs(node: Option>>) -> (i32, i32) { 24 | if node.is_some() { 25 | let node = node.as_ref().unwrap().borrow(); 26 | 27 | let l = bfs(node.left.clone()); 28 | let r = bfs(node.left.clone()); 29 | 30 | (node.val + l.1 + r.1, i32::max(l.0, l.1) + i32::max(r.0, r.1)) 31 | } else { 32 | (0, 0) 33 | } 34 | } 35 | 36 | i32::max(bfs(root.clone()).0, bfs(root).1) 37 | } 38 | } 39 | 40 | struct Solution {} 41 | -------------------------------------------------------------------------------- /src/leetcode/problem/rotate_the_box.rs: -------------------------------------------------------------------------------- 1 | // 1861. Rotating the Box, Medium 2 | // https://leetcode.com/problems/rotating-the-box/ 3 | impl Solution { 4 | pub fn rotate_the_box(grid: Vec>) -> Vec> { 5 | let [n, m] = [grid.len(), grid[0].len()]; 6 | 7 | // gravity -> move everything to the right 8 | let mut grid = grid; 9 | for i in 0..n { 10 | for j in (0..m).rev() { 11 | if grid[i][j] == '.' { 12 | let mut k = j; 13 | let mut stone_k = -1; 14 | while k > 0 && grid[i][k] != '*' { 15 | k -= 1; 16 | if grid[i][k] == '#' { 17 | stone_k = k as i32; 18 | } 19 | } 20 | if stone_k != -1 { 21 | grid[i][stone_k as usize] = '.'; 22 | grid[i][j] = '#'; 23 | } 24 | } 25 | } 26 | } 27 | 28 | let mut res = vec![vec!['.'; n]; m]; 29 | 30 | for i in 0..n { 31 | for j in 0..m { 32 | res[j][n - i - 1] = grid[i][j]; 33 | } 34 | } 35 | 36 | res 37 | } 38 | } 39 | 40 | struct Solution {} 41 | -------------------------------------------------------------------------------- /src/leetcode/problem/search_range.rs: -------------------------------------------------------------------------------- 1 | // 34. Find First and Last Position of Element in Sorted Array, Medium 2 | // https://leetcode.com/problems/find-first-and-last-position-of-element-in-sorted-array/ 3 | impl Solution { 4 | pub fn search_range(nums: Vec, target: i32) -> Vec { 5 | let mut ans = vec![]; 6 | 7 | match nums.binary_search(&target) { 8 | Ok(pos) => { 9 | let mut i = pos; 10 | let mut j = pos; 11 | while i > 0 && nums[i] == target { 12 | i -= 1; 13 | } 14 | while j < nums.len() - 1 && nums[i] == target { 15 | j += 1; 16 | } 17 | ans.append(&mut vec![i as i32 + 1, j as i32 - 1]); 18 | } 19 | Err(_) => ans.append(&mut vec![-1, -1]), 20 | } 21 | 22 | ans 23 | } 24 | } 25 | 26 | struct Solution {} 27 | -------------------------------------------------------------------------------- /src/leetcode/problem/solve_n_queens.rs: -------------------------------------------------------------------------------- 1 | use std::collections::{HashSet, VecDeque}; 2 | 3 | // 51. N-Queens, Hard 4 | // https://leetcode.com/problems/n-queens/ 5 | impl Solution { 6 | pub fn solve_n_queens(n: i32) -> Vec> { 7 | let mut board: Vec> = vec![vec![0; n as usize]; n as usize]; 8 | 9 | // Check if queen can be placed 10 | fn is_valid_placement(board: &Vec>, n: i32, i: i32, j: i32) -> bool { 11 | let mut queue = VecDeque::new(); 12 | 13 | queue.push_back((i, j, (1, 0))); 14 | queue.push_back((i, j, (1, 1))); 15 | queue.push_back((i, j, (0, 1))); 16 | queue.push_back((i, j, (-1, 1))); 17 | queue.push_back((i, j, (-1, 0))); 18 | queue.push_back((i, j, (-1, -1))); 19 | queue.push_back((i, j, (0, -1))); 20 | queue.push_back((i, j, (1, -1))); 21 | 22 | while !queue.is_empty() { 23 | let (x, y, direction) = queue.pop_front().unwrap(); 24 | 25 | if 0 <= x && x < n && 0 <= y && y < n { 26 | if board[x as usize][y as usize] == 1 { 27 | return false; 28 | } 29 | 30 | queue.push_back((x + direction.0, y + direction.1, direction)); 31 | } 32 | } 33 | 34 | true 35 | } 36 | 37 | let mut ans: Vec>> = vec![]; 38 | fn backtracking(ans: &mut Vec>>, board: &mut Vec>, n: usize, placed: usize, i: usize, j: usize) { 39 | if placed == n { 40 | ans.push(board.clone()); 41 | 42 | } else if i == n { 43 | 44 | } else if j == n { 45 | backtracking(ans, board, n, placed, i + 1, 0); 46 | } else { 47 | if is_valid_placement(board, n as i32, i as i32, j as i32) { 48 | board[i][j] = 1; 49 | backtracking(ans, board, n, placed + 1, i, j + 1); 50 | board[i][j] = 0; 51 | } 52 | 53 | backtracking(ans, board, n, placed, i, j + 1); 54 | } 55 | } 56 | 57 | backtracking(&mut ans, &mut board, n as usize, 0, 0, 0); 58 | 59 | ans.iter() 60 | .map(|ans| { 61 | ans.iter() 62 | .map(|row| row.iter().map(|ans| if *ans == 1 { "Q".to_string() } else { ".".to_string() }).collect::()) 63 | .collect() 64 | }) 65 | .collect() 66 | } 67 | } 68 | 69 | struct Solution {} 70 | 71 | #[cfg(test)] 72 | mod tests { 73 | use super::*; 74 | 75 | #[test] 76 | fn test_find_duplicates() { 77 | assert_eq!(Solution::solve_n_queens(4).len(), 2); 78 | } 79 | 80 | #[test] 81 | fn test_find_duplicates2() { 82 | assert_eq!(Solution::solve_n_queens(1).len(), 1); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/leetcode/problem/solve_sudoku.rs: -------------------------------------------------------------------------------- 1 | // 37. Sudoku Solver, Hard 2 | // https://leetcode.com/problems/sudoku-solver/ 3 | impl Solution { 4 | pub fn solve_sudoku(board: &mut Vec>) { 5 | fn get_valid_options(board: &mut Vec>, row_idx: usize, col_idx: usize) -> Vec { 6 | let mut row = ['.'; 9]; 7 | let mut col = ['.'; 9]; 8 | let mut block = ['.'; 9]; 9 | 10 | for i in 0..9 { 11 | row[i] = board[row_idx][i]; 12 | col[i] = board[i][col_idx]; 13 | block[i] = board[(row_idx / 3) * 3 + i / 3][(col_idx / 3) * 3 + i % 3]; 14 | } 15 | 16 | let mut options = vec!['1', '2', '3', '4', '5', '6', '7', '8', '9']; 17 | for i in 0..9 { 18 | if row[i] != '.' { 19 | options.retain(|&x| x != row[i]); 20 | } 21 | if col[i] != '.' { 22 | options.retain(|&x| x != col[i]); 23 | } 24 | if block[i] != '.' { 25 | options.retain(|&x| x != block[i]); 26 | } 27 | } 28 | 29 | options 30 | } 31 | 32 | fn backtrack(board_end: &mut Vec>, board: &mut Vec>, i: usize, j: usize) { 33 | if i == 9 { 34 | *board_end = board.clone(); 35 | return; 36 | } 37 | 38 | if j == 9 { 39 | backtrack(board_end, board, i + 1, 0); 40 | return; 41 | } 42 | 43 | if board[i][j] != '.' { 44 | backtrack(board_end, board, i, j + 1); 45 | return; 46 | } 47 | 48 | let options = get_valid_options(board, i, j); 49 | for option in options { 50 | board[i][j] = option; 51 | backtrack(board_end, board, i, j + 1); 52 | board[i][j] = '.'; 53 | } 54 | } 55 | 56 | let mut board_end = board.clone(); 57 | backtrack(board, &mut board_end, 0, 0); 58 | } 59 | } 60 | 61 | struct Solution {} 62 | 63 | #[cfg(test)] 64 | mod tests { 65 | use super::*; 66 | use crate::{vec_vec_char, vec_vec_i32}; 67 | 68 | #[test] 69 | fn test_solve_sudoku() { 70 | let mut board = vec_vec_char![ 71 | ['5', '3', '.', '.', '7', '.', '.', '.', '.'], 72 | ['6', '.', '.', '1', '9', '5', '.', '.', '.'], 73 | ['.', '9', '8', '.', '.', '.', '.', '6', '.'], 74 | ['8', '.', '.', '.', '6', '.', '.', '.', '3'], 75 | ['4', '.', '.', '8', '.', '3', '.', '.', '1'], 76 | ['7', '.', '.', '.', '2', '.', '.', '.', '6'], 77 | ['.', '6', '.', '.', '.', '.', '2', '8', '.'], 78 | ['.', '.', '.', '4', '1', '9', '.', '.', '5'], 79 | ['.', '.', '.', '.', '8', '.', '.', '7', '9'] 80 | ]; 81 | Solution::solve_sudoku(&mut board); 82 | assert_eq!( 83 | board, 84 | vec_vec_char![ 85 | ['5', '3', '4', '6', '7', '8', '9', '1', '2'], 86 | ['6', '7', '2', '1', '9', '5', '3', '4', '8'], 87 | ['1', '9', '8', '3', '4', '2', '5', '6', '7'], 88 | ['8', '5', '9', '7', '6', '1', '4', '2', '3'], 89 | ['4', '2', '6', '8', '5', '3', '7', '9', '1'], 90 | ['7', '1', '3', '9', '2', '4', '8', '5', '6'], 91 | ['9', '6', '1', '5', '3', '7', '2', '8', '4'], 92 | ['2', '8', '7', '4', '1', '9', '6', '3', '5'], 93 | ['3', '4', '5', '2', '8', '6', '1', '7', '9'] 94 | ] 95 | ); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/leetcode/problem/stock_span.rs: -------------------------------------------------------------------------------- 1 | // 901. Online Stock Span, Medium 2 | // https://leetcode.com/problems/online-stock-span/ 3 | impl StockSpanner { 4 | fn new() -> Self { 5 | StockSpanner { prices: vec![] } 6 | } 7 | 8 | fn next(&mut self, price: i32) -> i32 { 9 | self.prices.push(price); 10 | 11 | let mut i = 0; 12 | for d in (0..self.prices.len()).rev() { 13 | if self.prices[d] <= price { 14 | i += 1; 15 | } 16 | } 17 | 18 | i 19 | } 20 | } 21 | 22 | struct StockSpanner { 23 | prices: Vec, 24 | } 25 | -------------------------------------------------------------------------------- /src/leetcode/problem/sum_even_grandparent.rs: -------------------------------------------------------------------------------- 1 | // Definition for a binary tree node. 2 | #[derive(Debug, PartialEq, Eq)] 3 | pub struct TreeNode { 4 | pub val: i32, 5 | pub left: Option>>, 6 | pub right: Option>>, 7 | } 8 | 9 | impl TreeNode { 10 | #[inline] 11 | pub fn new(val: i32) -> Self { 12 | TreeNode { val, left: None, right: None } 13 | } 14 | } 15 | use std::cell::RefCell; 16 | use std::rc::Rc; 17 | 18 | // 1315. Sum of Nodes with Even-Valued Grandparent, Medium 19 | // https://leetcode.com/problems/sum-of-nodes-with-even-valued-grandparent/ 20 | impl Solution { 21 | pub fn sum_even_grandparent(root: Option>>) -> i32 { 22 | fn bfs(node: Option>>, sum: &mut i32, parent: i32, grandparent: i32) { 23 | if node.is_none() { 24 | return; 25 | } 26 | 27 | let node = node.as_ref().unwrap().borrow(); 28 | 29 | if grandparent != -1 && grandparent % 2 == 0 { 30 | *sum += node.val; 31 | } 32 | 33 | bfs(node.left.clone(), sum, node.val, parent); 34 | bfs(node.right.clone(), sum, node.val, parent); 35 | } 36 | 37 | let mut sum = 0; 38 | bfs(root, &mut sum, -1, -1); 39 | 40 | sum 41 | } 42 | } 43 | 44 | struct Solution {} 45 | -------------------------------------------------------------------------------- /src/leetcode/problem/total_n_queens.rs: -------------------------------------------------------------------------------- 1 | use std::collections::{HashSet, VecDeque}; 2 | 3 | // 52. N-Queens II, Hard 4 | // https://leetcode.com/problems/n-queens-ii/ 5 | impl Solution { 6 | pub fn total_n_queens(n: i32) -> i32 { 7 | let mut board: Vec> = vec![vec![0; n as usize]; n as usize]; 8 | 9 | // Check if queen can be placed 10 | fn is_valid_placement(board: &Vec>, n: i32, i: i32, j: i32) -> bool { 11 | let mut queue = VecDeque::new(); 12 | 13 | queue.push_back((i, j, (1, 0))); 14 | queue.push_back((i, j, (1, 1))); 15 | queue.push_back((i, j, (0, 1))); 16 | queue.push_back((i, j, (-1, 1))); 17 | queue.push_back((i, j, (-1, 0))); 18 | queue.push_back((i, j, (-1, -1))); 19 | queue.push_back((i, j, (0, -1))); 20 | queue.push_back((i, j, (1, -1))); 21 | 22 | while !queue.is_empty() { 23 | let (x, y, direction) = queue.pop_front().unwrap(); 24 | 25 | if 0 <= x && x < n && 0 <= y && y < n { 26 | if board[x as usize][y as usize] == 1 { 27 | return false; 28 | } 29 | 30 | queue.push_back((x + direction.0, y + direction.1, direction)); 31 | } 32 | } 33 | 34 | true 35 | } 36 | 37 | let mut ans: Vec>> = vec![]; 38 | fn backtracking(ans: &mut Vec>>, board: &mut Vec>, n: usize, placed: usize, i: usize, j: usize) { 39 | if placed == n { 40 | ans.push(board.clone()); 41 | 42 | } else if i == n { 43 | 44 | } else if j == n { 45 | backtracking(ans, board, n, placed, i + 1, 0); 46 | } else { 47 | if is_valid_placement(board, n as i32, i as i32, j as i32) { 48 | board[i][j] = 1; 49 | backtracking(ans, board, n, placed + 1, i, j + 1); 50 | board[i][j] = 0; 51 | } 52 | 53 | backtracking(ans, board, n, placed, i, j + 1); 54 | } 55 | } 56 | 57 | backtracking(&mut ans, &mut board, n as usize, 0, 0, 0); 58 | 59 | ans.len() as i32 60 | } 61 | } 62 | 63 | struct Solution {} 64 | 65 | #[cfg(test)] 66 | mod tests { 67 | use super::*; 68 | 69 | #[test] 70 | fn test_find_duplicates() { 71 | assert_eq!(Solution::total_n_queens(4), 2); 72 | } 73 | 74 | #[test] 75 | fn test_find_duplicates2() { 76 | assert_eq!(Solution::total_n_queens(1), 1); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/leetcode/problem/trap.rs: -------------------------------------------------------------------------------- 1 | use std::collections::VecDeque; 2 | 3 | // 42. Trapping Rain Water, Hard 4 | // https://leetcode.com/problems/trapping-rain-water/ 5 | impl Solution { 6 | pub fn trap(height: Vec) -> i32 { 7 | let mut ans = 0; 8 | let mut q = VecDeque::::new(); 9 | 10 | for (i, h) in height.iter().enumerate() { 11 | while !q.is_empty() && height[*q.back().unwrap()] < *h { 12 | let top = q.pop_back().unwrap(); 13 | if q.is_empty() { 14 | break; 15 | } 16 | 17 | let dist = i - q.back().unwrap() - 1; 18 | let bounded_height = i32::min(*h, height[*q.back().unwrap()]) - height[top]; 19 | ans += dist as i32 * bounded_height; 20 | } 21 | 22 | q.push_back(i); 23 | } 24 | 25 | ans 26 | } 27 | } 28 | 29 | struct Solution {} 30 | 31 | mod tests { 32 | use super::*; 33 | use crate::{vec_string, vec_vec_i32}; 34 | 35 | #[test] 36 | fn test_trap() { 37 | assert_eq!(Solution::trap(vec![0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1]), 6); 38 | } 39 | 40 | #[test] 41 | fn test_trap2() { 42 | assert_eq!(Solution::trap(vec![4, 2, 0, 3, 2, 5]), 9); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/leetcode/problem/two_sum.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | // 1. Two Sum, Easy 4 | // https://leetcode.com/problems/two-sum/ 5 | impl Solution { 6 | pub fn two_sum(nums: Vec, target: i32) -> Vec { 7 | let mut map: HashMap = HashMap::new(); 8 | 9 | for (i, num) in nums.iter().enumerate() { 10 | let rest = target - num; 11 | if let Some(j) = map.get(&rest) { 12 | return vec![*j, i as i32]; 13 | } 14 | map.insert(*num, i as i32); 15 | } 16 | 17 | return vec![]; 18 | } 19 | } 20 | 21 | struct Solution {} 22 | 23 | #[cfg(test)] 24 | mod tests { 25 | use super::*; 26 | 27 | #[test] 28 | fn test_two_sum() { 29 | assert_eq!(Solution::two_sum(vec![2, 7, 11, 15], 9), vec![0, 1]); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/leetcode/problem/unique_paths.rs: -------------------------------------------------------------------------------- 1 | // 62. Unique Paths, Medium 2 | // https://leetcode.com/problems/unique-paths/ 3 | impl Solution { 4 | pub fn unique_paths(m: i32, n: i32) -> i32 { 5 | let [n, m] = [n as usize, m as usize]; 6 | let mut dp = vec![vec![0; m]; n]; 7 | 8 | for i in 0..n { 9 | for j in 0..m { 10 | if i == 0 || j == 0 { 11 | dp[i][j] = 1; 12 | } else { 13 | dp[i][j] = dp[i - 1][j] + dp[i][j - 1]; 14 | } 15 | } 16 | } 17 | 18 | dp[n - 1][m - 1] 19 | } 20 | } 21 | 22 | struct Solution {} 23 | 24 | #[cfg(test)] 25 | mod tests { 26 | use super::*; 27 | 28 | #[test] 29 | fn test_unique_paths() { 30 | assert_eq!(Solution::unique_paths(3, 7), 28); 31 | } 32 | 33 | #[test] 34 | fn test_unique_paths2() { 35 | assert_eq!(Solution::unique_paths(2, 3), 3); 36 | } 37 | 38 | #[test] 39 | fn test_unique_paths3() { 40 | assert_eq!(Solution::unique_paths(7, 3), 28); 41 | } 42 | 43 | #[test] 44 | fn test_unique_paths4() { 45 | assert_eq!(Solution::unique_paths(3, 3), 6); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/leetcode/problem/zigzag_level_order.rs: -------------------------------------------------------------------------------- 1 | #[derive(Debug, PartialEq, Eq)] 2 | pub struct TreeNode { 3 | pub val: i32, 4 | pub left: Option>>, 5 | pub right: Option>>, 6 | } 7 | 8 | impl TreeNode { 9 | #[inline] 10 | pub fn new(val: i32) -> Self { 11 | TreeNode { val, left: None, right: None } 12 | } 13 | } 14 | 15 | use std::cell::RefCell; 16 | use std::rc::Rc; 17 | 18 | // 103. Binary Tree Zigzag Level Order Traversal, Medium 19 | // https://leetcode.com/problems/binary-tree-zigzag-level-order-traversal/ 20 | impl Solution { 21 | pub fn zigzag_level_order(root: Option>>) -> Vec> { 22 | let mut ans = vec![]; 23 | 24 | fn bfs(node: Option>>, ans: &mut Vec>, level: usize) { 25 | if let Some(node) = node { 26 | if ans.len() <= level { 27 | ans.push(vec![]); 28 | } 29 | 30 | if level % 2 == 0 { 31 | ans[level].push(node.borrow().val); 32 | } else { 33 | ans[level].insert(0, node.borrow().val); 34 | } 35 | 36 | bfs(node.borrow().left.clone(), ans, level + 1); 37 | bfs(node.borrow().right.clone(), ans, level + 1); 38 | } 39 | } 40 | 41 | bfs(root, &mut ans, 0); 42 | 43 | ans 44 | } 45 | } 46 | 47 | struct Solution {} 48 | -------------------------------------------------------------------------------- /src/leetcode/top_interview/array_and_string/group_anagrams.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | // 49. Group Anagrams, Medium 4 | // https://leetcode.com/problems/group-anagrams/ 5 | impl Solution { 6 | pub fn group_anagrams(strs: Vec) -> Vec> { 7 | let mut ans: Vec> = Vec::new(); 8 | let mut map: HashMap> = HashMap::new(); 9 | 10 | for str in strs { 11 | let mut chars = str.chars().collect::>(); 12 | chars.sort_unstable(); 13 | let key: String = chars.into_iter().collect(); 14 | if let Some(v) = map.get_mut(&key) { 15 | v.push(str); 16 | } else { 17 | map.insert(key, vec![str]); 18 | } 19 | } 20 | 21 | for (_, v) in map { 22 | ans.push(v); 23 | } 24 | ans 25 | } 26 | } 27 | 28 | struct Solution {} 29 | 30 | #[cfg(test)] 31 | mod tests { 32 | use super::*; 33 | use crate::{vec_string, vec_vec_i32, vec_vec_string}; 34 | 35 | #[test] 36 | fn test_group_anagrams() { 37 | assert_eq!(Solution::group_anagrams(vec_string!["eat", "tea", "tan", "ate", "nat", "bat"]).len(), 3); 38 | } 39 | 40 | #[test] 41 | fn test_group_anagrams2() { 42 | assert_eq!(Solution::group_anagrams(vec_string![""]), vec_vec_string![[""]]); 43 | } 44 | 45 | #[test] 46 | fn test_group_anagrams3() { 47 | assert_eq!(Solution::group_anagrams(vec_string!["a"]), vec_vec_string![["a"]]); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/leetcode/top_interview/array_and_string/increasing_triplet.rs: -------------------------------------------------------------------------------- 1 | use std::collections::VecDeque; 2 | 3 | // 334. Increasing Triplet Subsequence, Medium 4 | // https://leetcode.com/problems/increasing-triplet-subsequence/ 5 | impl Solution { 6 | pub fn increasing_triplet(nums: Vec) -> bool { 7 | let [mut small, mut big] = [std::i32::MAX, std::i32::MAX]; 8 | 9 | for num in nums { 10 | if num <= small { 11 | small = num; 12 | } else if num <= big { 13 | big = num; 14 | } else { 15 | return true; 16 | } 17 | } 18 | 19 | false 20 | } 21 | } 22 | 23 | struct Solution {} 24 | 25 | #[cfg(test)] 26 | mod tests { 27 | use super::*; 28 | use crate::{vec_string, vec_vec_i32, vec_vec_string}; 29 | 30 | #[test] 31 | fn test_increasing_triplet() { 32 | assert_eq!(Solution::increasing_triplet(vec![1, 2, 3, 4, 5]), true); 33 | } 34 | 35 | #[test] 36 | fn test_increasing_triplet2() { 37 | assert_eq!(Solution::increasing_triplet(vec![5, 4, 3, 2, 1]), false); 38 | } 39 | 40 | #[test] 41 | fn test_increasing_triplet3() { 42 | assert_eq!(Solution::increasing_triplet(vec![2, 1, 5, 0, 4, 6]), true); 43 | } 44 | 45 | #[test] 46 | fn test_increasing_triplet4() { 47 | assert_eq!(Solution::increasing_triplet(vec![20, 100, 10, 12, 5, 13]), true); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/leetcode/top_interview/array_and_string/length_of_longest_substring.rs: -------------------------------------------------------------------------------- 1 | // 3. Longest Substring Without Repeating Characters, Medium 2 | // https://leetcode.com/problems/longest-substring-without-repeating-characters/ 3 | impl Solution { 4 | pub fn length_of_longest_substring(s: String) -> i32 { 5 | let mut max = 0; 6 | 7 | let mut q = Vec::new(); 8 | for ch in s.chars() { 9 | while q.contains(&ch) { 10 | q.remove(0); 11 | } 12 | q.push(ch); 13 | max = max.max(q.len() as i32); 14 | } 15 | 16 | max 17 | } 18 | } 19 | 20 | struct Solution {} 21 | 22 | #[cfg(test)] 23 | mod tests { 24 | use super::*; 25 | use crate::vec_vec_i32; 26 | 27 | #[test] 28 | fn test_length_of_longest_substring() { 29 | assert_eq!(Solution::length_of_longest_substring("abcabcbb".to_string()), 3); 30 | } 31 | 32 | #[test] 33 | fn test_length_of_longest_substring2() { 34 | assert_eq!(Solution::length_of_longest_substring("bbbbb".to_string()), 1); 35 | } 36 | 37 | #[test] 38 | fn test_length_of_longest_substring3() { 39 | assert_eq!(Solution::length_of_longest_substring("pwwkew".to_string()), 3); 40 | } 41 | 42 | #[test] 43 | fn test_length_of_longest_substring4() { 44 | assert_eq!(Solution::length_of_longest_substring("".to_string()), 0); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/leetcode/top_interview/array_and_string/longest_palindrome.rs: -------------------------------------------------------------------------------- 1 | // 5. Longest Palindromic Substring, Medium 2 | // https://leetcode.com/problems/longest-palindromic-substring/ 3 | impl Solution { 4 | pub fn longest_palindrome(s: String) -> String { 5 | let n = s.len(); 6 | if n <= 1 { 7 | return s; 8 | } 9 | 10 | let chars = s.chars().collect::>(); 11 | 12 | let mut ans = chars[0].to_string(); 13 | let mut dp = vec![vec![false; n]; n]; 14 | for i in 0..n { 15 | dp[i][i] = true; 16 | } 17 | 18 | let mut max_len = 0; 19 | for end in 1..n { 20 | for start in 0..end { 21 | if chars[start] == chars[end] && (end - start == 1 || dp[start + 1][end - 1]) { 22 | dp[start][end] = true; 23 | if max_len < end - start + 1 { 24 | max_len = end - start + 1; 25 | ans = chars[start..=end].iter().collect::(); 26 | } 27 | } 28 | } 29 | } 30 | 31 | ans 32 | } 33 | } 34 | 35 | struct Solution {} 36 | 37 | #[cfg(test)] 38 | mod tests { 39 | use super::*; 40 | use crate::{vec_string, vec_vec_i32, vec_vec_string}; 41 | 42 | #[test] 43 | fn test_longest_palindrome() { 44 | assert_eq!(Solution::longest_palindrome("babad".to_string()), "bab".to_string()); 45 | } 46 | 47 | #[test] 48 | fn test_longest_palindrome2() { 49 | assert_eq!(Solution::longest_palindrome("cbbd".to_string()), "bb".to_string()); 50 | } 51 | 52 | #[test] 53 | fn test_longest_palindrome3() { 54 | assert_eq!(Solution::longest_palindrome("a".to_string()), "a".to_string()); 55 | } 56 | 57 | #[test] 58 | fn test_longest_palindrome4() { 59 | assert_eq!(Solution::longest_palindrome("ac".to_string()), "a".to_string()); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/leetcode/top_interview/array_and_string/mod.rs: -------------------------------------------------------------------------------- 1 | mod group_anagrams; 2 | mod increasing_triplet; 3 | mod length_of_longest_substring; 4 | mod longest_palindrome; 5 | mod set_zeroes; -------------------------------------------------------------------------------- /src/leetcode/top_interview/array_and_string/set_zeroes.rs: -------------------------------------------------------------------------------- 1 | // 73. Set Matrix Zeroes, Medium 2 | // https://leetcode.com/problems/set-matrix-zeroes/submissions/ 3 | impl Solution { 4 | pub fn set_zeroes(matrix: &mut Vec>) { 5 | let [n, m] = [matrix.len(), matrix[0].len()]; 6 | let mut zeros: Vec<(usize, usize)> = Vec::new(); 7 | 8 | for i in 0..n { 9 | for j in 0..m { 10 | if matrix[i][j] == 0 { 11 | zeros.push((i, j)); 12 | } 13 | } 14 | } 15 | 16 | for (zi, zj) in zeros { 17 | for i in 0..n { 18 | matrix[i][zj] = 0; 19 | } 20 | for j in 0..m { 21 | matrix[zi][j] = 0; 22 | } 23 | } 24 | } 25 | } 26 | 27 | struct Solution {} 28 | 29 | #[cfg(test)] 30 | mod tests { 31 | use super::*; 32 | use crate::vec_vec_i32; 33 | 34 | #[test] 35 | fn test_set_zeroes() { 36 | let mut matrix = vec_vec_i32![[1, 1, 1], [1, 0, 1], [1, 1, 1]]; 37 | Solution::set_zeroes(&mut matrix); 38 | assert_eq!(matrix, vec_vec_i32![[1, 0, 1], [0, 0, 0], [1, 0, 1]]); 39 | } 40 | 41 | #[test] 42 | fn test_set_zeroes2() { 43 | let mut matrix = vec_vec_i32![[0, 1, 2, 0], [3, 4, 5, 2], [1, 3, 1, 5]]; 44 | Solution::set_zeroes(&mut matrix); 45 | assert_eq!(matrix, vec_vec_i32![[0, 0, 0, 0], [0, 4, 5, 0], [0, 3, 1, 0]]); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/leetcode/top_interview/dynamic_programming/can_jump.rs: -------------------------------------------------------------------------------- 1 | use std::collections::VecDeque; 2 | 3 | // 55. Jump Game, Medium 4 | // https://leetcode.com/problems/jump-game/ 5 | impl Solution { 6 | pub fn can_jump(mut nums: Vec) -> bool { 7 | let n = nums.len() - 1; 8 | let mut pos: VecDeque = VecDeque::new(); 9 | pos.push_back(0); 10 | 11 | while !pos.is_empty() && pos.back().unwrap() < &n { 12 | let curr = *pos.back().unwrap(); 13 | let next = nums[curr] as usize; 14 | 15 | if next == 0 { 16 | pos.pop_back(); 17 | } else { 18 | nums[curr] -= 1; 19 | pos.push_back(curr + next); 20 | } 21 | } 22 | 23 | !pos.is_empty() && pos.back().unwrap() >= &n 24 | } 25 | } 26 | 27 | struct Solution {} 28 | 29 | #[cfg(test)] 30 | mod tests { 31 | use super::*; 32 | use crate::{vec_string, vec_vec_i32, vec_vec_string}; 33 | 34 | #[test] 35 | fn test_can_jump() { 36 | assert_eq!(Solution::can_jump(vec![2, 3, 1, 1, 4]), true); 37 | } 38 | 39 | #[test] 40 | fn test_can_jump2() { 41 | assert_eq!(Solution::can_jump(vec![3, 2, 1, 0, 4]), false); 42 | } 43 | 44 | #[test] 45 | fn test_can_jump3() { 46 | assert_eq!(Solution::can_jump(vec![3, 0, 8, 2, 0, 0, 1]), true); 47 | } 48 | 49 | #[test] 50 | fn test_can_jump4() { 51 | assert_eq!(Solution::can_jump(vec![0]), true); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/leetcode/top_interview/dynamic_programming/mod.rs: -------------------------------------------------------------------------------- 1 | mod can_jump; 2 | -------------------------------------------------------------------------------- /src/leetcode/top_interview/linked_list/add_two_numbers.rs: -------------------------------------------------------------------------------- 1 | // Definition for singly-linked list. 2 | #[derive(PartialEq, Eq, Clone, Debug)] 3 | pub struct ListNode { 4 | pub val: i32, 5 | pub next: Option>, 6 | } 7 | 8 | impl ListNode { 9 | #[inline] 10 | fn new(val: i32) -> Self { 11 | ListNode { next: None, val } 12 | } 13 | } 14 | 15 | pub trait ListMaker { 16 | fn link(val: i32, next: Option>) -> Option> { 17 | Some(Box::new(ListNode { val, next })) 18 | } 19 | } 20 | 21 | impl ListMaker for Option> {} 22 | 23 | // 2. Add Two Numbers, Medium 24 | // https://leetcode.com/problems/add-two-numbers/ 25 | impl Solution { 26 | pub fn add_two_numbers(l1: Option>, l2: Option>) -> Option> { 27 | let mut sum: Option> = None; 28 | 29 | let mut p1 = &l1; 30 | let mut p2 = &l2; 31 | let mut p3 = &mut sum; 32 | let mut carry = 0; 33 | 34 | while p1.is_some() || p2.is_some() || carry != 0 { 35 | let mut val = carry; 36 | 37 | if let Some(n1) = p1.as_ref() { 38 | val += n1.val; 39 | p1 = &n1.next; 40 | } 41 | 42 | if let Some(n2) = p2.as_ref() { 43 | val += n2.val; 44 | p2 = &n2.next; 45 | } 46 | 47 | carry = val / 10; 48 | *p3 = Option::>::link(val % 10, None); 49 | p3 = &mut p3.as_mut().unwrap().next; 50 | } 51 | sum 52 | } 53 | } 54 | 55 | struct Solution {} 56 | -------------------------------------------------------------------------------- /src/leetcode/top_interview/linked_list/mod.rs: -------------------------------------------------------------------------------- 1 | mod add_two_numbers; -------------------------------------------------------------------------------- /src/leetcode/top_interview/mod.rs: -------------------------------------------------------------------------------- 1 | mod array_and_string; 2 | mod dynamic_programming; 3 | mod linked_list; 4 | mod others; 5 | mod sorting; -------------------------------------------------------------------------------- /src/leetcode/top_interview/others/majority_element.rs: -------------------------------------------------------------------------------- 1 | use std::collections::VecDeque; 2 | 3 | // 169. Majority Element, Easy 4 | // https://leetcode.com/problems/majority-element/solution/ 5 | impl Solution { 6 | pub fn majority_element(nums: Vec) -> i32 { 7 | let mut count = 0; 8 | let mut cand: Option = None; 9 | 10 | for num in nums { 11 | if cand.is_none() || count == 0 { 12 | cand = Some(num); 13 | count = 1; 14 | } else if cand.unwrap() == num { 15 | count += 1; 16 | } else if count > 0 { 17 | count -= 1; 18 | } 19 | } 20 | 21 | cand.unwrap() 22 | } 23 | } 24 | 25 | struct Solution {} 26 | 27 | #[cfg(test)] 28 | mod tests { 29 | use super::*; 30 | 31 | #[test] 32 | fn test_majority_element() { 33 | assert_eq!(Solution::majority_element(vec![3, 2, 3]), 3); 34 | } 35 | 36 | #[test] 37 | fn test_majority_element2() { 38 | assert_eq!(Solution::majority_element(vec![2, 2, 1, 1, 1, 2, 2]), 2); 39 | } 40 | 41 | #[test] 42 | fn test_majority_element3() { 43 | assert_eq!(Solution::majority_element(vec![3, 3, 4]), 3); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/leetcode/top_interview/others/mod.rs: -------------------------------------------------------------------------------- 1 | mod majority_element; -------------------------------------------------------------------------------- /src/leetcode/top_interview/sorting/mod.rs: -------------------------------------------------------------------------------- 1 | mod sort_colors; -------------------------------------------------------------------------------- /src/leetcode/top_interview/sorting/sort_colors.rs: -------------------------------------------------------------------------------- 1 | // 75. Sort Colors, Medium 2 | // https://leetcode.com/problems/sort-colors/ 3 | impl Solution { 4 | pub fn sort_colors(nums: &mut Vec) { 5 | let n = nums.len(); 6 | if n <= 1 { 7 | return; 8 | } 9 | 10 | let mut swapped = true; 11 | 12 | while swapped { 13 | swapped = false; 14 | for i in 0..n - 1 { 15 | if nums[i] > nums[i + 1] { 16 | nums.swap(i, i + 1); 17 | swapped = true; 18 | break; 19 | } 20 | } 21 | } 22 | } 23 | } 24 | 25 | struct Solution {} 26 | 27 | #[cfg(test)] 28 | mod tests { 29 | use super::*; 30 | use crate::{vec_string, vec_vec_i32, vec_vec_string}; 31 | 32 | #[test] 33 | fn test_sort_colors() { 34 | let mut colors = vec![2, 0, 2, 1, 1, 0]; 35 | Solution::sort_colors(&mut colors); 36 | assert_eq!(colors, vec![0, 0, 1, 1, 2, 2]); 37 | } 38 | 39 | #[test] 40 | fn test_sort_colors2() { 41 | let mut colors = vec![2, 0, 1]; 42 | Solution::sort_colors(&mut colors); 43 | assert_eq!(colors, vec![0, 1, 2]); 44 | } 45 | 46 | #[test] 47 | fn test_sort_colors3() { 48 | let mut colors = vec![0]; 49 | Solution::sort_colors(&mut colors); 50 | assert_eq!(colors, vec![0]); 51 | } 52 | 53 | #[test] 54 | fn test_sort_colors4() { 55 | let mut colors = vec![1]; 56 | Solution::sort_colors(&mut colors); 57 | assert_eq!(colors, vec![1]); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/leetcode/util/mod.rs: -------------------------------------------------------------------------------- 1 | mod vec_vec; 2 | -------------------------------------------------------------------------------- /src/leetcode/util/vec_vec.rs: -------------------------------------------------------------------------------- 1 | #[macro_export] 2 | macro_rules! vec_vec_i32 { 3 | ($($tail:tt),*) => { 4 | vec![$(vec!$tail),*] as Vec> 5 | }; 6 | } 7 | 8 | #[macro_export] 9 | macro_rules! vec_string { 10 | ($($tail:tt),*) => { 11 | vec![$($tail.to_string()),*] as Vec 12 | }; 13 | } 14 | 15 | #[macro_export] 16 | macro_rules! vec_vec_string { 17 | ($($tail:tt),*) => { 18 | vec![$(vec_string!$tail),*] as Vec> 19 | }; 20 | } 21 | 22 | #[macro_export] 23 | macro_rules! vec_vec_char { 24 | ($($tail:tt),*) => { 25 | vec![$(vec!$tail),*] as Vec> 26 | }; 27 | } -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused_must_use)] 2 | #![allow(unused_imports)] 3 | #![allow(dead_code)] 4 | 5 | mod binarysearch; 6 | mod leetcode; 7 | 8 | use regex::Regex; 9 | use std::fs::File; 10 | use std::io::{BufRead, BufReader, Write}; 11 | use std::{env, error::Error, fs}; 12 | use walkdir::WalkDir; 13 | 14 | fn main() { 15 | println!("Hello Leetcode!"); 16 | gen_table(); 17 | } 18 | 19 | pub type Result = std::result::Result>; 20 | 21 | fn gen_table() -> Result<()> { 22 | let re_title = Regex::new(r"// (\d+). (.+), (.+)$").unwrap(); 23 | let re_url = Regex::new(r"// (https?:.*)").unwrap(); 24 | 25 | let mut entries: Vec<(i32, String, String, String, String)> = Vec::new(); 26 | for entry in WalkDir::new("./src").follow_links(true).into_iter().filter_map(|e| e.ok()) { 27 | let f_path = &entry.path().to_string_lossy().to_string(); 28 | 29 | if f_path.ends_with(".rs") { 30 | let input = File::open(f_path)?; 31 | let buffered = BufReader::new(input); 32 | let mut entry = (0, "".to_string(), "".to_string(), "".to_string(), "".to_string()); 33 | for line in buffered.lines() { 34 | let str = line.as_ref().unwrap(); 35 | if re_title.is_match(str) { 36 | let m = re_title.captures(str).unwrap(); 37 | entry.0 = m.get(1).unwrap().as_str().parse::().unwrap(); 38 | entry.1 = m.get(2).unwrap().as_str().to_string(); 39 | entry.2 = m.get(3).unwrap().as_str().to_string(); 40 | } 41 | if re_url.is_match(str) { 42 | let m = re_url.captures(str).unwrap(); 43 | entry.3 = m.get(1).unwrap().as_str().to_string(); 44 | entry.4 = f_path.clone(); 45 | } 46 | 47 | if entry.0 != 0 && !entry.3.is_empty() { 48 | entries.push(entry.clone()); 49 | entry = (0, "".to_string(), "".to_string(), "".to_string(), "".to_string()); 50 | } 51 | } 52 | } 53 | } 54 | 55 | entries.sort(); 56 | 57 | entries.iter_mut().for_each(|f| match f.2.as_str() { 58 | "Easy" => { 59 | f.2 = "![easy](https://shields.io/badge/-easy-green)".to_string(); 60 | } 61 | "Medium" => { 62 | f.2 = "![medium](https://shields.io/badge/-medium-yellow)".to_string(); 63 | } 64 | "Hard" => { 65 | f.2 = "![hard](https://shields.io/badge/-hard-red)".to_string(); 66 | } 67 | _ => {} 68 | }); 69 | 70 | println!("## Solutions ({}) ", entries.len()); 71 | println!( 72 | r#"| No. | Title | Solution | Problem | Difficulty | 73 | |:---:|:------|:--------:|:-------:|:----------:|"# 74 | ); 75 | for entry in entries { 76 | println!( 77 | "| {} | {} | [Rust](https://github.com/martinxxd/leetcode-rust/tree/master/{}) | [Leetcode]({}) | {} |", 78 | entry.0, entry.1, entry.4, entry.3, entry.2 79 | ); 80 | } 81 | 82 | Ok(()) 83 | } 84 | --------------------------------------------------------------------------------