Jan LeetCoding Challenge Rust Solution
Table of Contents
290. Word Pattern⌗
use std::collections::HashMap;
impl Solution {
pub fn word_pattern(pattern: String, s: String) -> bool {
if pattern.len() != s.matches(' ').count() + 1 {
return false;
}
let mut char_to_string = HashMap::new();
let mut string_to_char = HashMap::new();
for (c, w) in pattern.chars().zip(s.split_whitespace()) {
if char_to_string.contains_key(&c) && char_to_string[&c] != w {
return false;
}
if string_to_char.contains_key(w) && string_to_char[w] != c {
return false;
}
char_to_string.insert(c, w);
string_to_char.insert(w, c);
}
true
}
}
520. Detect Capital⌗
impl Solution {
pub fn detect_capital_use(word: String) -> bool {
let mut all_cap = word.chars().filter(|c| c.is_lowercase()).count() == 0;
let mut all_lower = word.chars().filter(|c| c.is_uppercase()).count() == 0;
let mut title = word
.char_indices()
.filter(|&(i, c)| i == 0 && c.is_uppercase() || c.is_lowercase())
.count() == word.len();
all_cap || all_lower || title
}
}
944. Delete Columns to Make Sorted⌗
impl Solution {
pub fn min_deletion_size(mut strs: Vec<String>) -> i32 {
let mut ret = 0;
for j in 0..strs[0].len() {
for i in 1..strs.len() {
if strs[i - 1].as_bytes()[j] > strs[i].as_bytes()[j] {
ret += 1;
break;
}
}
}
ret
}
}
2244. Minimum Rounds to Complete All Tasks⌗
impl Solution {
pub fn minimum_rounds(mut tasks: Vec<i32>) -> i32 {
let n = tasks.len();
tasks.sort();
let mut dp = vec![i32::MAX >> 1; n + 5];
dp[0] = 0;
dp[2] = 1;
for i in 3..=n {
dp[i] = dp[i - 2].min(dp[i - 3]) + 1;
}
let mut ret = 0;
let mut cnt = 1;
for i in 1..=n {
if i == n || tasks[i - 1] != tasks[i] {
let r = dp[cnt];
if r >= i32::MAX >> 1 {
return -1;
}
ret += r;
cnt = 1;
} else {
cnt += 1;
}
}
ret
}
}
452. Minimum Number of Arrows to Burst Balloons⌗
impl Solution {
pub fn find_min_arrow_shots(mut points: Vec<Vec<i32>>) -> i32 {
points.sort_by(|a, b| a[0].cmp(&b[0]));
let mut ret = 0;
let mut right = points[0][1];
for i in 1..points.len() {
if points[i][0] > right {
ret += 1;
right = points[i][1];
} else {
right = right.min(points[i][1]);
}
}
ret + 1
}
}
1833. Maximum Ice Cream Bars⌗
impl Solution {
pub fn max_ice_cream(mut costs: Vec<i32>, mut coins: i32) -> i32 {
costs.sort();
let n = costs.len();
for i in 0..=n {
if i == n || coins < costs[i] {
return i as i32;
}
coins -= costs[i];
}
-1
}
}
134. Gas Station⌗
impl Solution {
pub fn can_complete_circuit(gas: Vec<i32>, cost: Vec<i32>) -> i32 {
let total_gain = gas.iter().zip(cost.iter()).map(|(g, c)| g - c).sum::<i32>();
if total_gain < 0 {
return -1;
}
let (mut g, mut ret) = (0, 0);
for i in 0..gas.len() {
g += gas[i] - cost[i];
if g < 0 {
g = 0;
ret = i + 1;
}
}
ret as i32
}
}
149. Max Points on a Line⌗
use std::collections::HashMap;
impl Solution {
pub fn max_points(points: Vec<Vec<i32>>) -> i32 {
let n = points.len();
let mut ret = 0;
let mut slope_map = HashMap::new();
for i in 0..n {
let mut max = 1;
for j in 0..n {
if i != j {
let s = slope(&points[i], &points[j]);
let v = slope_map.entry(s).or_insert(1);
*v += 1;
max = max.max(*v);
}
}
slope_map.clear();
ret = ret.max(max);
}
ret
}
}
fn slope(p0: &[i32], p1: &[i32]) -> String {
let mut dy = p0[1] - p1[1];
let mut dx = p0[0] - p1[0];
if dy == 0 {
return "0".into();
}
if dx == 0 {
return "inf".into();
}
let gcd = gcd(dy, dx);
dy /= gcd;
dx /= gcd;
format!("{}/{}", dy, dx)
}
fn gcd(a: i32, b: i32) -> i32 {
if b == 0 {
return a;
}
gcd(b, a % b)
}
144. Binary Tree Preorder Traversal⌗
use std::rc::Rc;
use std::cell::RefCell;
type Node = Option<Rc<RefCell<TreeNode>>>;
impl Solution {
pub fn preorder_traversal(root: Node) -> Vec<i32> {
let mut ret = vec![];
f(&root, &mut ret);
ret
}
}
fn f(root: &Node, ret: &mut Vec<i32>) {
if let Some(root) = root {
let root = root.borrow();
ret.push(root.val);
f(&root.left, ret);
f(&root.right, ret);
}
}
100. Same Tree⌗
use std::rc::Rc;
use std::cell::RefCell;
type Node = Option<Rc<RefCell<TreeNode>>>;
impl Solution {
pub fn is_same_tree(p: Node, q: Node) -> bool {
fn f(p: &Node, q: &Node) -> bool {
if p.is_none() && q.is_none() {
return true;
}
if p.is_none() || q.is_none() {
return false;
}
let p = p.as_ref().unwrap().borrow();
let q = q.as_ref().unwrap().borrow();
p.val == q.val && f(&p.left, &q.left) && f(&p.right, &q.right)
}
f(&p, &q)
}
}
1443. Minimum Time to Collect All Apples in a Tree⌗
struct Env {
graph: Vec<Vec<usize>>,
has_apple: Vec<bool>
}
impl Solution {
pub fn min_time(n: i32, edges: Vec<Vec<i32>>, has_apple: Vec<bool>) -> i32 {
let n = n as usize;
let mut graph = vec![vec![]; n];
for edge in &edges {
let (u, v) = (edge[0] as usize, edge[1] as usize);
graph[u].push(v);
graph[v].push(u);
}
fn f(env: &Env, u: usize, parent: usize) -> (i32, i32) {
let mut seconds = 0;
let mut apples = env.has_apple[u as usize] as i32;
for &v in &env.graph[u] {
if v == parent { continue; }
let r = f(env, v, u);
if r.1 > 0 {
seconds += r.0 + 2;
}
apples += r.1;
}
(seconds, apples)
}
let env = Env { graph, has_apple };
f(&env, 0, n).0
}
}
1519. Number of Nodes in the Sub-Tree With the Same Label⌗
struct Env<'a> {
graph: Vec<Vec<usize>>,
labels: &'a [u8],
}
impl Solution {
pub fn count_sub_trees(n: i32, edges: Vec<Vec<i32>>, labels: String) -> Vec<i32> {
let n = n as usize;
let mut graph = vec![vec![]; n];
for edge in &edges {
let (u, v) = (edge[0] as usize, edge[1] as usize);
graph[u].push(v);
graph[v].push(u);
}
let mut ret = vec![0; n];
fn f(env: &Env, u: usize, p: usize, ret: &mut Vec<i32>) -> Vec<i32> {
let mut count = vec![0; 26];
for &v in &env.graph[u] {
if v != p {
let r = f(env, v, u, ret);
for i in 0..count.len() {
count[i] += r[i];
}
}
}
let lable = (env.labels[u] - b'a') as usize;
count[lable] += 1;
ret[u] = count[lable];
count
}
let env = Env {
graph,
labels: labels.as_bytes(),
};
f(&env, 0, n, &mut ret);
ret
}
}
2246. Longest Path With Different Adjacent Characters⌗
impl Solution {
pub fn longest_path(parent: Vec<i32>, s: String) -> i32 {
let n = parent.len();
let mut graph = vec![vec![]; n];
for (u, &p) in parent.iter().enumerate().skip(1) {
graph[p as usize].push(u);
}
fn f(graph: &Vec<Vec<usize>>, s: &[u8], u: usize, ret: &mut i32) -> i32 {
let mut child1 = 0;
let mut child2 = 0;
for &v in &graph[u] {
let r = f(graph, s, v, ret);
if s[u] != s[v] {
if r >= child1 {
child2 = child1;
child1 = r;
} else if r >= child2 {
child2 = r;
}
}
}
*ret = (*ret).max(child1 + child2 + 1);
child1 + 1
}
let mut ret = 0;
f(&graph, s.as_bytes(), 0, &mut ret);
ret
}
}
1061. Lexicographically Smallest Equivalent String⌗
struct UnionFind {
parent: Vec<usize>,
rank: Vec<usize>,
}
impl UnionFind {
fn with_capacity(n: usize) -> Self {
Self {
parent: (0..n).collect(),
rank: vec![0; n],
}
}
fn find(&mut self, u: usize) -> usize {
if self.parent[u] == u {
return u;
}
self.parent[u] = self.find(self.parent[u]);
self.parent[u]
}
fn union(&mut self, u: usize, v: usize) -> bool {
let pu = self.find(u);
let pv = self.find(v);
if pu == pv {
return true;
}
if self.rank[pu] < self.rank[pv] {
self.parent[pu] = pv;
} else {
self.parent[pv] = pu;
if self.rank[pu] == self.rank[pv] {
self.rank[pu] += 1;
}
}
false
}
}
impl Solution {
pub fn smallest_equivalent_string(s1: String, s2: String, base_str: String) -> String {
let mut uf = UnionFind::with_capacity(128);
s1.as_bytes()
.iter()
.zip(s2.as_bytes().iter())
.for_each(|(&a, &b)| {
uf.union(a as usize, b as usize);
});
let mut group = vec![vec![]; 128];
(b'a'..=b'z').for_each(|c| {
let root = uf.find(c as usize);
group[root].push(c);
});
group.iter_mut().for_each(|g| g.sort());
let mut ret = String::with_capacity(s1.len());
base_str.as_bytes().iter().for_each(|&c| {
let root = uf.find(c as usize);
ret.push(group[root][0] as char);
});
ret
}
}
2421. Number of Good Paths⌗
use std::{
cmp::Reverse,
collections::{BTreeMap, HashMap},
};
struct UnionFind {
parent: Vec<usize>,
rank: Vec<usize>,
}
impl UnionFind {
fn with_capacity(n: usize) -> Self {
Self {
parent: (0..n).collect(),
rank: vec![0; n],
}
}
fn find(&mut self, u: usize) -> usize {
if self.parent[u] == u {
return u;
}
self.parent[u] = self.find(self.parent[u]);
self.parent[u]
}
fn union(&mut self, u: usize, v: usize) -> bool {
let pu = self.find(u);
let pv = self.find(v);
if pu == pv {
return true;
}
if self.rank[pu] < self.rank[pv] {
self.parent[pu] = pv;
} else {
self.parent[pv] = pu;
if self.rank[pu] == self.rank[pv] {
self.rank[pu] += 1;
}
}
false
}
}
impl Solution {
pub fn number_of_good_paths(vals: Vec<i32>, edges: Vec<Vec<i32>>) -> i32 {
let n = vals.len();
let mut graph = vec![vec![]; n];
let mut same_val_nodes = BTreeMap::new();
for i in 0..n {
same_val_nodes
.entry(vals[i])
.or_insert_with(Vec::new)
.push(i);
}
for edge in edges {
let u = edge[0] as usize;
let v = edge[1] as usize;
if vals[v] <= vals[u] {
graph[u].push(v);
}
if vals[u] <= vals[v] {
graph[v].push(u);
}
}
let mut ret = n;
let mut uf = UnionFind::with_capacity(n);
let mut groups: HashMap<usize, usize> = HashMap::new();
for (_, nodes) in same_val_nodes {
for &u in &nodes {
for &v in &graph[u] {
uf.union(u, v);
}
}
groups.clear();
for u in nodes {
let e = groups.entry(uf.find(u)).or_default();
*e += 1;
}
for &cnt in groups.values() {
if cnt > 1 {
ret += (cnt * (cnt - 1)) / 2;
}
}
}
ret as i32
}
}
57. Insert Interval⌗
impl Solution {
pub fn insert(intervals: Vec<Vec<i32>>, mut new_interval: Vec<i32>) -> Vec<Vec<i32>> {
let n = intervals.len();
let mut ret = vec![];
let mut i = 0;
while i < n && intervals[i][1] < new_interval[0] {
ret.push(intervals[i].clone());
i += 1;
}
while i < n && new_interval[1] >= intervals[i][0] {
new_interval[0] = new_interval[0].min(intervals[i][0]);
new_interval[1] = new_interval[1].max(intervals[i][1]);
i += 1;
}
ret.push(new_interval);
while i < n {
ret.push(intervals[i].clone());
i += 1;
}
ret
}
}
926. Flip String to Monotone Increasing⌗
impl Solution {
pub fn min_flips_mono_incr(s: String) -> i32 {
let n = s.len();
let s = s.as_bytes();
let mut total_zeros = 0;
for i in 0..n {
if s[i] == b'0' {
total_zeros += 1;
}
}
let mut ret = i32::MAX >> 1;
let mut left_ones = 0;
let mut left_zeros = 0;
for i in 0..=n {
ret = ret.min(left_ones + (total_zeros - left_zeros));
if i < n {
if s[i] == b'0' {
left_zeros += 1;
} else {
left_ones += 1;
}
}
}
ret
}
}
918. Maximum Sum Circular Subarray⌗
impl Solution {
pub fn max_subarray_sum_circular(nums: Vec<i32>) -> i32 {
let mut dp_min = nums[0];
let mut dp_max = nums[0];
let mut sum = nums[0];
let mut min = dp_min;
let mut max = dp_max;
for &num in nums.iter().skip(1) {
dp_min = (dp_min + num).min(num);
dp_max = (dp_max + num).max(num);
sum += num;
min = min.min(dp_min);
max = max.max(dp_max);
}
if max < 0 {
max
} else {
max.max(sum - min)
}
}
}
974. Subarray Sums Divisible by K⌗
use std::collections::HashMap;
impl Solution {
pub fn subarrays_div_by_k(mut nums: Vec<i32>, k: i32) -> i32 {
let min = nums.iter().min().unwrap();
let m = (min.abs() / k) + 1;
for num in nums.iter_mut() {
*num += m * k;
}
let mut ret = 0;
let mut sum = 0;
let mut map = HashMap::new();
map.insert(0, 1);
for num in nums {
sum += num;
let e = map.entry(sum % k).or_default();
ret += *e;
*e += 1;
}
ret
}
}
491. Non-decreasing Subsequences⌗
impl Solution {
pub fn find_subsequences(nums: Vec<i32>) -> Vec<Vec<i32>> {
fn f(i: usize, last: i32, nums: &Vec<i32>, sub: &mut Vec<i32>, ret: &mut Vec<Vec<i32>>) {
if i >= nums.len() {
if sub.len() >= 2 {
ret.push(sub.clone());
}
return;
}
if sub.len() == 0 || nums[i] >= last {
sub.push(nums[i]);
f(i + 1, nums[i], nums, sub, ret);
sub.pop();
}
if nums[i] != last {
f(i + 1, last, nums, sub, ret);
}
}
let mut ret = vec![];
let mut sub = vec![];
f(0, i32::MIN >> 1, &nums, &mut sub, &mut ret);
ret
}
}
131. Palindrome Partitioning⌗
impl Solution {
pub fn partition(s: String) -> Vec<Vec<String>> {
fn check(s: &String, mut l: usize, mut r: usize) -> bool {
while l < r {
if s.as_bytes()[l] != s.as_bytes()[r] {
return false;
}
l += 1;
r -= 1;
}
true
}
fn f(s: &String, i: usize, parts: &mut Vec<String>, ret: &mut Vec<Vec<String>>) {
if i >= s.len() {
ret.push(parts.clone());
return;
}
for j in i..s.len() {
if check(s, i, j) {
parts.push(s[i..=j].into());
f(s, j + 1, parts, ret);
parts.pop();
}
}
}
let mut parts = vec![];
let mut ret = vec![];
f(&s, 0, &mut parts, &mut ret);
ret
}
}
997. Find the Town Judge⌗
impl Solution {
pub fn find_judge(n: i32, trust: Vec<Vec<i32>>) -> i32 {
let n = n as usize;
let mut in_degree = vec![0; n + 1];
let mut out_degree = vec![0; n + 1];
for edge in trust {
let (u, v) = (edge[0], edge[1]);
out_degree[u as usize] += 1;
in_degree[v as usize] += 1;
}
let mut ret = -1;
for i in 1..=n {
if out_degree[i] == 0 && in_degree[i] == n - 1 {
if ret != -1 {
return -1;
}
ret = i as i32;
}
}
ret
}
}
909. Snakes and Ladders⌗
impl Solution {
pub fn snakes_and_ladders(board: Vec<Vec<i32>>) -> i32 {
let n = board.len();
let mut queue = vec![];
let mut visited = vec![vec![false; n]; n];
queue.push(1);
visited[n - 1][0] = true;
let mut level = 0;
while !queue.is_empty() {
let mut next_queue = vec![];
for _ in 0..queue.len() {
let curr = queue.pop().unwrap();
if curr == n * n {
return level;
}
for next in (curr + 1)..=(curr + 6).min(n * n) {
let i = (next - 1) / n;
let j = (next - 1) % n;
let revi = n - 1 - i;
let revj = n - 1 - j;
let i = revi;
let j = if revi & 1 == n & 1 { revj } else { j };
if visited[i][j] {
continue;
}
visited[i][j] = true;
if board[i][j] == -1 {
next_queue.push(next);
} else {
next_queue.push(board[i][j] as usize);
}
}
}
queue = next_queue;
level += 1;
}
-1
}
}
2359. Find Closest Node to Given Two Nodes⌗
use std::collections::VecDeque;
impl Solution {
pub fn closest_meeting_node(edges: Vec<i32>, node1: i32, node2: i32) -> i32 {
let n = edges.len();
let mut graph = vec![vec![]; n];
for i in 0..n {
if edges[i] != -1 {
graph[i].push(edges[i] as usize);
}
}
fn dijkstra(graph: &Vec<Vec<usize>>, s: usize) -> Vec<i32> {
// because all the weight is 1, we could using normal queue to
// reduce the time complexity
let mut queue = VecDeque::new();
let mut dist = vec![i32::MAX >> 1; graph.len()];
dist[s] = 0;
queue.push_back((dist[s], s));
while !queue.is_empty() {
let node = queue.pop_front().unwrap();
let (d, u) = (node.0, node.1);
if d != dist[u] {
continue;
}
for &v in &graph[u] {
if d + 1 < dist[v] {
dist[v] = d + 1;
queue.push_back((dist[v], v));
}
}
}
dist
}
let d1 = dijkstra(&graph, node1 as usize);
let d2 = dijkstra(&graph, node2 as usize);
let mut ret = -1;
let mut min = i32::MAX >> 1;
for i in 0..n {
let d = d1[i].max(d2[i]);
if d < min {
min = d;
ret = i as i32;
}
}
ret
}
}
787. Cheapest Flights Within K Stops⌗
impl Solution {
pub fn find_cheapest_price(n: i32, flights: Vec<Vec<i32>>, src: i32, dst: i32, k: i32) -> i32 {
let mut dist = vec![i32::MAX >> 1; n as usize];
dist[src as usize] = 0;
for _ in 0..=k {
let prev_dist = dist.clone();
for edge in &flights {
let (u, v, w) = (edge[0] as usize, edge[1] as usize, edge[2]);
dist[v] = dist[v].min(prev_dist[u] + w);
}
}
let ret = dist[dst as usize];
if ret >= i32::MAX >> 1 {
-1
} else {
ret
}
}
}
472. Concatenated Words⌗
use std::collections::HashSet;
impl Solution {
pub fn find_all_concatenated_words_in_a_dict(words: Vec<String>) -> Vec<String> {
let mut word_set = HashSet::new();
for word in &words {
word_set.insert(word.as_str());
}
let mut ret = vec![];
for &word in &word_set {
if Solution::f(word, 0, 0, &word_set) {
ret.push(word.into());
}
}
ret
}
fn f(word: &str, cnt: usize, i: usize, words: &HashSet<&str>) -> bool {
if i >= word.len() {
return cnt >= 2;
}
for j in i..word.len() {
let sub = &word[i..=j];
if words.contains(sub) && Solution::f(word, cnt + 1, j + 1, words) {
return true;
}
}
false
}
}
352. Data Stream as Disjoint Intervals⌗
struct SummaryRanges {
data: Vec<Vec<i32>>,
}
impl SummaryRanges {
fn new() -> Self {
Self {
data: vec![
vec![i32::MIN >> 1, i32::MIN >> 1],
vec![i32::MAX >> 1, i32::MAX >> 1],
],
}
}
fn add_num(&mut self, value: i32) {
let l = self.data.partition_point(|range| range[1] < value);
let left = &self.data[l - 1];
let right = &self.data[l];
let mid = value;
fn contains(range: &[i32], v: i32) -> bool {
range[0] <= v && v <= range[1]
}
if left[1] + 1 == mid && mid == right[0] - 1 {
self.data[l - 1][1] = right[1];
self.data.remove(l);
} else if left[1] + 1 == mid || contains(left, mid) {
self.data[l - 1][1] = left[1].max(mid);
} else if mid == right[0] - 1 || contains(right, mid) {
self.data[l][0] = right[0].min(mid);
} else {
self.data.insert(l, vec![mid, mid]);
}
}
fn get_intervals(&self) -> Vec<Vec<i32>> {
self.data[1..self.data.len() - 1].to_vec()
}
}
460. LFU Cache⌗
use std::collections::{BTreeSet, HashMap};
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone)]
struct CacheEntry {
count: usize,
used_time: usize,
key: i32,
value: i32,
}
struct LFUCache {
queue: BTreeSet<CacheEntry>,
cache: HashMap<i32, CacheEntry>,
capacity: usize,
time: usize,
}
impl LFUCache {
fn new(capacity: i32) -> Self {
Self {
queue: BTreeSet::new(),
cache: HashMap::new(),
capacity: capacity as usize,
time: 0,
}
}
fn get(&mut self, key: i32) -> i32 {
self.time += 1;
if let Some(entry) = self.cache.get_mut(&key) {
self.queue.remove(entry);
entry.used_time = self.time;
entry.count += 1;
self.queue.insert(entry.clone());
return entry.value;
}
-1
}
fn put(&mut self, key: i32, value: i32) {
self.time += 1;
if self.capacity == 0 {
return;
}
if let Some(entry) = self.cache.get_mut(&key) {
self.queue.remove(entry);
entry.used_time = self.time;
entry.count += 1;
entry.value = value;
self.queue.insert(entry.clone());
} else {
if self.cache.len() >= self.capacity {
let entry = self.queue.iter().next().unwrap().clone();
self.cache.remove(&entry.key);
self.queue.remove(&entry);
}
let entry = CacheEntry {
key,
value,
count: 1,
used_time: self.time,
};
self.cache.entry(key).or_insert(entry.clone());
self.queue.insert(entry);
}
}
}
1137. N-th Tribonacci Number⌗
impl Solution {
pub fn tribonacci(n: i32) -> i32 {
let n = n as usize;
let mut memo = vec![-1; n + 1];
fn f(memo: &mut [i32], n: usize) -> i32 {
if n <= 2 {
return (n as i32).min(1);
}
if memo[n] != -1 {
return memo[n];
}
memo[n] = f(memo, n - 1) + f(memo, n - 2) + f(memo, n - 3);
memo[n]
}
f(&mut memo, n)
}
}
1626. Best Team With No Conflicts⌗
use std::cmp::Ordering;
impl Solution {
pub fn best_team_score(scores: Vec<i32>, ages: Vec<i32>) -> i32 {
let n = scores.len();
let mut index: Vec<usize> = (0..n).collect();
let mut memo = vec![vec![-1; n + 1]; n];
index.sort_by(|&a, &b| {
let r = ages[a].cmp(&ages[b]);
if r == Ordering::Equal {
return scores[a].cmp(&scores[b]);
}
r
});
fn f(
scores: &Vec<i32>,
index: &Vec<usize>,
memo: &mut Vec<Vec<i32>>,
i: usize,
p: usize,
) -> i32 {
if i >= scores.len() {
return 0;
}
if memo[i][p] != -1 {
return memo[i][p];
}
let mut ret = f(scores, index, memo, i + 1, p);
if p == scores.len() || scores[index[i]] >= scores[index[p]] {
ret = ret.max(f(scores, index, memo, i + 1, i) + scores[index[i]]);
}
memo[i][p] = ret;
memo[i][p]
}
f(&scores, &index, &mut memo, 0, n)
}
}
Read other posts