Oct LeetCoding Challenge Rust Solution
Table of Contents
91. Decode Ways⌗
impl Solution {
pub fn num_decodings(s: String) -> i32 {
Solution::dp(s.as_bytes(), 0, &mut vec![0; s.len()])
}
fn dp(s: &[u8], i: usize, memo: &mut [i32]) -> i32 {
if i >= s.len() {
return 1;
}
if memo[i] != 0 {
return memo[i];
}
let mut ret = 0;
let mut num = 0;
for j in i..s.len() {
num = num * 10 + (s[j] - b'0') as i32;
if num == 0 || num > 26 {
break;
}
ret += Solution::dp(s, j + 1, memo);
}
memo[i] = ret;
ret
}
}
1155. Number of Dice Rolls With Target Sum⌗
struct Env {
k: i32,
memo: Vec<Vec<i32>>,
}
impl Solution {
pub fn num_rolls_to_target(n: i32, k: i32, target: i32) -> i32 {
fn dp(env: &mut Env, n: i32, t: i32) -> i32 {
if n == 0 && t == 0 {
return 1;
}
if n < 0 || t < 0 {
return 0;
}
let un = n as usize;
let ut = t as usize;
if env.memo[un][ut] != -1 {
return env.memo[un][ut];
}
let mut ret = 0;
for i in 1..=env.k {
ret += dp(env, n - 1, t - i);
ret %= 1_000_000_007;
}
env.memo[un][ut] = ret;
ret
}
let memo = vec![vec![-1; (target + 1) as usize]; (n + 1) as usize];
dp(&mut Env { k, memo }, n, target)
}
}
1578. Minimum Time to Make Rope Colorful⌗
impl Solution {
pub fn min_cost(colors: String, needed_time: Vec<i32>) -> i32 {
let colors = colors.as_bytes();
let n = needed_time.len();
let mut sum = 0;
let mut max = 0;
let mut i = 0;
let mut j = 0;
let mut ret = 0;
while j <= n {
if j == n || colors[i] != colors[j] {
ret += sum - max;
i = j;
sum = 0;
max = 0;
}
if j < n {
sum += needed_time[j];
max = max.max(needed_time[j]);
}
j += 1;
}
ret
}
}
112. Path Sum⌗
use std::cell::RefCell;
use std::rc::Rc;
type Node = Option<Rc<RefCell<TreeNode>>>;
impl Solution {
pub fn has_path_sum(root: Node, target_sum: i32) -> bool {
fn dfs(root: &Node, n: i32) -> bool {
if let Some(root) = root {
let root = root.borrow();
if root.left.is_none() && root.right.is_none() {
return root.val == n;
}
return dfs(&root.left, n - root.val) || dfs(&root.right, n - root.val);
}
false
}
dfs(&root, target_sum)
}
}
623. Add One Row to Tree⌗
use std::cell::RefCell;
use std::rc::Rc;
type Node = Option<Rc<RefCell<TreeNode>>>;
impl Solution {
pub fn add_one_row(root: Node, val: i32, depth: i32) -> Node {
fn internal(root: Node, val: i32, depth: i32, is_left: bool) -> Node {
if depth == 1 {
let mut node = TreeNode::new(val);
if is_left {
node.left = root;
} else {
node.right = root;
}
return Some(Rc::new(RefCell::new(node)));
}
if let Some(root) = root.as_ref() {
let mut root = root.borrow_mut();
root.left = internal(root.left.take(), val, depth - 1, true);
root.right = internal(root.right.take(), val, depth - 1, false);
}
root
}
internal(root, val, depth, true)
}
}
981. Time Based Key-Value Store⌗
use std::collections::{BTreeMap, HashMap};
struct TimeMap {
map: HashMap<String, BTreeMap<i32, String>>,
}
impl TimeMap {
fn new() -> Self {
TimeMap {
map: HashMap::new(),
}
}
fn set(&mut self, key: String, value: String, timestamp: i32) {
self.map.entry(key).or_default().insert(timestamp, value);
}
fn get(&self, key: String, timestamp: i32) -> String {
self.map
.get(&key)
.and_then(|m| m.range(..=timestamp).next_back().map(|(_, v)| v.clone()))
.unwrap_or_default()
}
}
732. My Calendar III⌗
use std::collections::BTreeMap;
struct MyCalendarThree {
diff: BTreeMap<i32, i32>,
}
impl MyCalendarThree {
fn new() -> Self {
MyCalendarThree {
diff: BTreeMap::new(),
}
}
fn book(&mut self, start: i32, end: i32) -> i32 {
*self.diff.entry(start).or_default() += 1;
*self.diff.entry(end).or_default() -= 1;
let mut s = 0;
let mut ret = 0;
for d in self.diff.values() {
s += d;
ret = ret.max(s);
}
ret
}
}
16. 3Sum Closest⌗
impl Solution {
pub fn three_sum_closest(mut nums: Vec<i32>, target: i32) -> i32 {
nums.sort();
let mut ret = 0;
let mut diff = i32::MAX >> 1;
for i in 0..nums.len() {
let mut j = i + 1;
let mut k = nums.len() - 1;
while j < k {
let sum = nums[i] + nums[j] + nums[k];
let d = (sum - target).abs();
if d < diff {
diff = d;
ret = sum;
if d == 0 {
break;
}
}
if sum < target {
j += 1;
} else {
k -= 1;
}
}
}
ret
}
}
653. Two Sum IV - Input is a BST⌗
use std::cell::RefCell;
use std::collections::HashSet;
use std::rc::Rc;
type Node = Option<Rc<RefCell<TreeNode>>>;
impl Solution {
pub fn find_target(root: Node, k: i32) -> bool {
fn internal(root: &Node, k: i32, set: &mut HashSet<i32>) -> bool {
if let Some(root) = root {
let root = root.borrow();
if set.contains(&(k - root.val)) {
return true;
}
set.insert(root.val);
return internal(&root.left, k, set) || internal(&root.right, k, set);
}
false
}
internal(&root, k, &mut HashSet::new())
}
}
1328. Break a Palindrome⌗
impl Solution {
pub fn break_palindrome(mut palindrome: String) -> String {
let n = palindrome.len();
if n == 1 {
return "".into();
}
let mut p = palindrome.into_bytes();
for i in 0..n / 2 {
if p[i] > b'a' {
p[i] = b'a';
return String::from_utf8(p).unwrap();
}
}
p[n - 1] = b'b';
String::from_utf8(p).unwrap()
}
}
334. Increasing Triplet Subsequence⌗
impl Solution {
pub fn increasing_triplet(nums: Vec<i32>) -> bool {
let mut m1 = i32::MAX;
let mut m2 = i32::MAX;
for &num in &nums {
if num <= m1 {
m1 = num;
} else if num <= m2 {
m2 = num;
} else {
return true;
}
}
false
}
}
976. Largest Perimeter Triangle⌗
impl Solution {
pub fn largest_perimeter(mut nums: Vec<i32>) -> i32 {
nums.sort();
for w in nums.windows(3).rev() {
if let &[a, b, c] = w {
if a + b > c {
return a + b + c;
}
}
}
0
}
}
237. Delete Node in a Linked List⌗
impl Solution {
pub fn delete_node(node: Option<Box<ListNode>>) {
if let Some(mut node) = node {
let next = node.next.unwrap();
node.val = next.val;
node.next = next.next;
}
}
}
2095. Delete the Middle Node of a Linked List⌗
type Node = Option<Box<ListNode>>;
impl Solution {
pub fn delete_middle(head: Node) -> Node {
fn node_len(head: &Node) -> usize {
if let Some(head) = head {
return node_len(&head.next) + 1;
}
0
}
fn node_delete(head: Node, n: usize) -> Node {
if let Some(mut head) = head {
if n == 0 {
return head.next;
} else {
head.next = node_delete(head.next, n - 1);
return Some(head);
}
}
None
}
let len = node_len(&head);
node_delete(head, len / 2)
}
}
1531. String Compression II⌗
struct Env<'a> {
s: &'a [u8],
memo: Vec<Vec<i32>>,
}
impl Solution {
pub fn get_length_of_optimal_compression(s: String, k: i32) -> i32 {
fn run(c: usize) -> i32 {
if c == 1 {
return 1;
}
if c <= 9 {
return 2;
}
if c <= 99 {
return 3;
}
4
}
fn internal(env: &mut Env, i: usize, k: usize) -> i32 {
if env.s.len() - i <= k {
return 0;
}
if env.memo[i][k] != -1 {
return env.memo[i][k];
}
let mut ret = i32::MAX >> 1;
let mut keep_count = 0;
let mut counter = vec![0; 26];
for j in i..env.s.len() {
let at = (env.s[j] - b'a') as usize;
counter[at] += 1;
keep_count = keep_count.max(counter[at]);
let remove_count = j - i + 1 - keep_count;
if remove_count <= k {
ret = ret.min(internal(env, j + 1, k - remove_count) + run(keep_count));
}
}
env.memo[i][k] = ret;
ret
}
internal(&mut Env {
s: s.as_bytes(),
memo: vec![vec![-1; 101]; 101],
}, 0, k as usize)
}
}
1335. Minimum Difficulty of a Job Schedule⌗
struct Env {
n: usize,
max: Vec<Vec<i32>>,
memo: Vec<Vec<i32>>,
}
impl Solution {
pub fn min_difficulty(job_difficulty: Vec<i32>, d: i32) -> i32 {
fn internal(env: &mut Env, i: usize, p: usize) -> i32 {
if i >= env.n {
return i32::MAX >> 1;
}
if p == 0 {
return env.max[i][env.n - 1];
}
if env.memo[i][p] != -1 {
return env.memo[i][p];
}
let mut ret = i32::MAX >> 1;
for j in i..env.n {
ret = ret.min(env.max[i][j] + internal(env, j + 1, p - 1));
}
env.memo[i][p] = ret;
ret
}
// build max array
let n = job_difficulty.len();
let mut max = vec![vec![0; n]; n];
for i in 0..n {
let mut m = job_difficulty[i];
for j in i..n {
m = m.max(job_difficulty[j]);
max[i][j] = m;
}
}
// compute the result
let d = d as usize;
let ret = internal(
&mut Env {
n,
max,
memo: vec![vec![-1; d]; n],
},
0,
d - 1,
);
// check invalid solution
if ret == i32::MAX >> 1 {
-1
} else {
ret
}
}
}
1832. Check if the Sentence Is Pangram⌗
impl Solution {
pub fn check_if_pangram(sentence: String) -> bool {
let mut has = vec![false; 26];
let sentence = sentence.as_bytes();
for c in sentence {
has[(c - b'a') as usize] = true;
}
for c in 0..26 {
if !has[c] {
return false;
}
}
true
}
}
38. Count and Say⌗
impl Solution {
pub fn count_and_say(n: i32) -> String {
if n == 1 {
return "1".to_string();
}
let r = Solution::count_and_say(n - 1);
let r = r.as_bytes();
let mut ret = String::new();
let mut cnt = 1;
for i in 1..=r.len() {
if i == r.len() || r[i] != r[i - 1] {
ret.push_str(&cnt.to_string());
ret.push(r[i - 1] as char);
cnt = 0;
}
cnt += 1;
}
ret
}
}
692. Top K Frequent Words⌗
use std::collections::HashMap;
impl Solution {
pub fn top_k_frequent(words: Vec<String>, k: i32) -> Vec<String> {
let mut map: HashMap<String, i32> = HashMap::new();
for word in words {
*map.entry(word).or_default() += 1;
}
let mut entries = vec![];
for entry in map {
entries.push(entry);
}
entries.sort_by(|a, b| {
use std::cmp::Ordering;
let ret = b.1.cmp(&a.1);
match ret {
Ordering::Equal => a.0.cmp(&b.0),
_ => ret
}
});
let mut ret = vec![];
for entry in entries {
if ret.len() >= k as usize {
break;
}
ret.push(entry.0);
}
ret
}
}
12. Integer to Roman⌗
impl Solution {
pub fn int_to_roman(mut num: i32) -> String {
let A = vec![1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1];
let B = vec!["M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"];
let mut ret = "".to_string();
for i in 0..A.len() {
while num >= A[i] {
ret.push_str(B[i]);
num -= A[i];
}
}
ret
}
}
219. Contains Duplicate II⌗
use std::collections::HashMap;
impl Solution {
pub fn contains_nearby_duplicate(nums: Vec<i32>, k: i32) -> bool {
let mut map = HashMap::new();
for j in 0..nums.len() as i32 {
let num = nums[j as usize];
let i = map.entry(num).or_insert(j - k - 1);
if j - *i <= k {
return true;
}
*i = j;
}
false
}
}
76. Minimum Window Substring⌗
use std::collections::HashMap;
impl Solution {
pub fn min_window(s: String, t: String) -> String {
let mut tmap = HashMap::new();
for c in t.as_bytes() {
*tmap.entry(c).or_insert(0) += 1;
}
let mut wmap = HashMap::new();
let mut win_count = 0;
let (mut min, mut l, mut r) = (usize::MAX >> 1, 0, 0);
let (mut i, mut j) = (0, 0);
let s = s.as_bytes();
while j < s.len() {
let mut c = s[j];
*wmap.entry(c).or_insert(0) += 1;
if tmap.contains_key(&c) && wmap[&c] == tmap[&c] {
win_count += 1;
}
while i <= j && win_count == tmap.len() {
if j - i + 1 < min {
min = j - i + 1;
l = i;
r = j;
}
c = s[i];
i += 1;
*wmap.entry(c).or_insert(0) -= 1;
if tmap.contains_key(&c) && wmap[&c] < tmap[&c] {
win_count -= 1;
}
}
j += 1;
}
if min == usize::MAX >> 1 {
return "".into();
}
String::from_utf8(s[l..=r].into()).unwrap()
}
}
645. Set Mismatch⌗
use std::collections::HashSet;
impl Solution {
pub fn find_error_nums(nums: Vec<i32>) -> Vec<i32> {
let mut ret = vec![0; 2];
let n = nums.len() as i32;
let mut set = HashSet::new();
for num in nums {
if set.contains(&num) {
ret[0] = num;
}
set.insert(num);
}
for num in 1..=n {
if !set.contains(&num) {
ret[1] = num;
break;
}
}
ret
}
}
1239. Maximum Length of a Concatenated String with Unique Characters⌗
impl Solution {
pub fn max_length(arr: Vec<String>) -> i32 {
let bits = arr.iter().map(|s| {
let mut bit = 0;
for c in s.as_bytes() {
let mask = 1 << (c - b'a');
if bit & mask != 0 {
return 0;
}
bit |= mask;
}
bit
}).collect();
fn internal(bits: &Vec<i32>, i: usize, state: i32) -> i32 {
if i >= bits.len() {
return 0;
}
let l = internal(bits, i + 1, state);
let r = if state & bits[i] == 0 {
internal(bits, i + 1, state | bits[i]) + bits[i].count_ones() as i32
} else {
0
};
l.max(r)
}
internal(&bits, 0, 0)
}
}
1662. Check If Two String Arrays are Equivalent⌗
impl Solution {
pub fn array_strings_are_equal(word1: Vec<String>, word2: Vec<String>) -> bool {
fn toString(w: Vec<String>) -> String {
w.iter().fold(String::new(), |mut ret, a| {
ret.push_str(a);
ret
})
}
toString(word1) == toString(word2)
}
}
523. Continuous Subarray Sum⌗
use std::collections::HashMap;
impl Solution {
pub fn check_subarray_sum(nums: Vec<i32>, k: i32) -> bool {
let mut map: HashMap<i32, i32> = HashMap::new();
map.insert(0, -1);
let mut sum = 0;
for j in 0..nums.len() as i32 {
sum += nums[j as usize];
let key = sum % k;
let i = map.get(&key).unwrap_or(&j);
if j - i >= 2 {
return true;
}
map.entry(key).or_insert(j);
}
false
}
}
835. Image Overlap⌗
impl Solution {
pub fn largest_overlap(img1: Vec<Vec<i32>>, img2: Vec<Vec<i32>>) -> i32 {
let n = img1.len() as i32;
let mut ret = 0;
for yoff in -n..=n {
for xoff in -n..=n {
let mut overlap = 0;
for y in 0..n {
for x in 0..n {
let y_ = y + yoff;
let x_ = x + xoff;
if y_ < 0 || y_ >= n || x_ < 0 || x_ >= n {
continue;
}
if img1[y as usize][x as usize] & img2[y_ as usize][x_ as usize] == 1 {
overlap += 1;
}
}
}
ret = ret.max(overlap);
}
}
ret
}
}
49. Group Anagrams⌗
use std::collections::HashMap;
impl Solution {
pub fn group_anagrams(strs: Vec<String>) -> Vec<Vec<String>> {
fn hash(str: &String) -> Vec<usize> {
let mut cnt = vec![0; 26];
for c in str.as_bytes() {
cnt[(c - b'a') as usize] += 1;
}
cnt
}
let mut map = HashMap::with_capacity(strs.len());
for str in strs {
map.entry(hash(&str)).or_insert_with(Vec::new).push(str);
}
map.into_values().collect()
}
}
2136. Earliest Possible Day of Full Bloom⌗
impl Solution {
pub fn earliest_full_bloom(plant_time: Vec<i32>, grow_time: Vec<i32>) -> i32 {
let n = plant_time.len();
let mut index = (0..n).collect::<Vec<usize>>();
index.sort_by(|&a, &b| {
grow_time[b].cmp(&grow_time[a])
});
let mut pt = 0;
let mut ret = 0;
for at in index {
pt += plant_time[at];
ret = ret.max(pt + grow_time[at]);
}
ret
}
}
1293. Shortest Path in a Grid with Obstacles Elimination⌗
use std::{cmp::Reverse, collections::BinaryHeap};
impl Solution {
pub fn shortest_path(grid: Vec<Vec<i32>>, k: i32) -> i32 {
let dirs = [[1, 0], [0, 1], [-1, 0], [0, -1]];
let m = grid.len();
let n = grid[0].len();
let mut queue = BinaryHeap::new();
let mut cost = vec![i32::MAX >> 1; m * n];
queue.push(Reverse((0, 0, 0, 0)));
cost[0] = 0;
let target = m * n - 1;
while !queue.is_empty() {
if let Some(Reverse((d, i, j, c))) = queue.pop() {
let u = i * n + j;
if u == target {
return d;
}
if c != cost[u] {
continue;
}
for dir in dirs {
let _i = i as i32 + dir[0];
let _j = j as i32 + dir[1];
if _i < 0 || _i >= m as i32 || _j < 0 || _j >= n as i32 {
continue;
}
let (_i, _j) = (_i as usize, _j as usize);
let v = _i * n + _j;
let w = grid[_i][_j] & 1;
if c + w > k {
continue;
}
if c + w < cost[v] {
cost[v] = c + w;
queue.push(Reverse((d + 1, _i, _j, cost[v])));
}
}
}
}
-1
}
}
766. Toeplitz Matrix⌗
impl Solution {
pub fn is_toeplitz_matrix(matrix: Vec<Vec<i32>>) -> bool {
for i in 1..matrix.len() {
for j in 1..matrix[0].len() {
if matrix[i][j] != matrix[i - 1][j - 1] {
return false;
}
}
}
true
}
}
Read other posts