Moved every rust file from src/bin to src, added tests for each problem, added lib.rs file
This commit is contained in:
parent
955182542e
commit
cede8e5f45
33 changed files with 552 additions and 342 deletions
|
@ -1,20 +0,0 @@
|
||||||
fn main() {
|
|
||||||
println!("{}", is_match(String::from("acaabbaccbbacaabbbb"), String::from("a*.*b*.*a*aa*a*")))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_match(s: String, p: String) -> bool {
|
|
||||||
let (s, p) = (s.as_bytes(), p.as_bytes());
|
|
||||||
let mut dp = vec![vec![false; p.len() + 1]; s.len() + 1];
|
|
||||||
dp[s.len()][p.len()] = true;
|
|
||||||
for i in (0..=s.len()).rev() {
|
|
||||||
for j in (0..p.len()).rev() {
|
|
||||||
let first_match = i < s.len() && (p[j] == b'.' || p[j] == s[i]);
|
|
||||||
if j + 1 < p.len() && p[j + 1] == b'*' {
|
|
||||||
dp[i][j] = first_match && dp[i + 1][j] || dp[i][j + 2];
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
dp[i][j] = first_match && dp[i + 1][j + 1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return dp[0][0];
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
fn main() {
|
|
||||||
println!("{}", max_area(vec![1,8,6,2,5,4,8,3,7]));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn max_area(height: Vec<i32>) -> i32 {
|
|
||||||
let (mut left, mut right) = (0, height.len() - 1);
|
|
||||||
let mut max_water = 0;
|
|
||||||
while left < right {
|
|
||||||
let x = (right - left) as i32; let h;
|
|
||||||
if height[left] < height[right] {
|
|
||||||
h = height[left];
|
|
||||||
left += 1;
|
|
||||||
} else {
|
|
||||||
h = height[right];
|
|
||||||
right -= 1;
|
|
||||||
};
|
|
||||||
max_water = max_water.max(h * x);
|
|
||||||
}
|
|
||||||
return max_water;
|
|
||||||
}
|
|
|
@ -1,35 +0,0 @@
|
||||||
fn main() {
|
|
||||||
println!("{}", int_to_roman(1994));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn int_to_roman(num: i32) -> String {
|
|
||||||
let roman_nums = vec!['M', 'D', 'C', 'L', 'X', 'V', 'I'];
|
|
||||||
let mut result = String::with_capacity(15);
|
|
||||||
let (mut num, mut divisor) = (num, 1000);
|
|
||||||
for i in (0..roman_nums.len()).step_by(2) {
|
|
||||||
let roman = roman_nums[i];
|
|
||||||
let roman_amount = num / divisor;
|
|
||||||
match roman_amount {
|
|
||||||
0 => (),
|
|
||||||
1..=3 => {
|
|
||||||
for _ in 0..roman_amount { result.push(roman); }
|
|
||||||
},
|
|
||||||
5..=8 => {
|
|
||||||
let complement = roman_nums[i - 1];
|
|
||||||
result.push(complement);
|
|
||||||
for _ in 0..(roman_amount-5) { result.push(roman); }
|
|
||||||
},
|
|
||||||
4 | 9 => {
|
|
||||||
let complement_index = i - roman_amount as usize / 4;
|
|
||||||
let complement = roman_nums[complement_index];
|
|
||||||
result.push(roman);
|
|
||||||
result.push(complement);
|
|
||||||
},
|
|
||||||
_ => ()
|
|
||||||
}
|
|
||||||
num %= divisor;
|
|
||||||
divisor /= 10;
|
|
||||||
}
|
|
||||||
if result.is_empty() { result.push('0'); }
|
|
||||||
return result;
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
fn main() {
|
|
||||||
println!("{}", roman_to_int(String::from("MCMXCIV")));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn roman_to_int(s: String) -> i32 {
|
|
||||||
s.chars().fold(0, |acc, c| {
|
|
||||||
let num = match c {
|
|
||||||
'M' => 1000, 'D' => 500, 'C' => 100, 'L' => 50,
|
|
||||||
'X' => 10, 'V' => 5, 'I' => 1, _ => 0
|
|
||||||
};
|
|
||||||
acc + num - 2 * (acc % num)
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
fn main() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn longest_common_prefix(strs: Vec<String>) -> String {
|
|
||||||
let mut result = String::with_capacity(200);
|
|
||||||
let first_str = strs[0].as_bytes();
|
|
||||||
if first_str.is_empty() { return result; }
|
|
||||||
for i in 0..first_str.len() {
|
|
||||||
let c = first_str[i];
|
|
||||||
for j in 1..strs.len() {
|
|
||||||
if i >= strs[j].len() || c != strs[j].as_bytes()[i] {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result.push(c as char);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
fn main() {
|
|
||||||
println!("{:?}", three_sum(vec![-1,0,1,2,-1,-4]));
|
|
||||||
println!("{:?}", three_sum(vec![0,0,0,0,0,0]));
|
|
||||||
println!("{:?}", three_sum(vec![-2,0,0,2,2]));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn three_sum(mut nums: Vec<i32>) -> Vec<Vec<i32>> {
|
|
||||||
let mut result = Vec::<Vec<i32>>::new();
|
|
||||||
nums.sort();
|
|
||||||
for i in 0..nums.len()-2 {
|
|
||||||
if i > 0 && nums[i] == nums[i - 1] { continue; }
|
|
||||||
let (mut j, mut k) = (i + 1, nums.len() - 1);
|
|
||||||
while j < k {
|
|
||||||
if j > i + 1 && nums[j - 1] == nums[j] {
|
|
||||||
j += 1; continue;
|
|
||||||
}
|
|
||||||
if k < nums.len() - 1 && nums[k + 1] == nums[k] {
|
|
||||||
k -= 1; continue;
|
|
||||||
}
|
|
||||||
match (nums[i] + nums[j] + nums[k]).cmp(&0) {
|
|
||||||
std::cmp::Ordering::Less => { j += 1; },
|
|
||||||
std::cmp::Ordering::Greater => { k -= 1 },
|
|
||||||
std::cmp::Ordering::Equal => {
|
|
||||||
result.push(vec![nums[i], nums[j], nums[k]]);
|
|
||||||
j += 1; k -= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
fn main() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn three_sum_closest(nums: Vec<i32>, target: i32) -> i32 {
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,17 +0,0 @@
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
println!("{:?}", two_sum(vec![2,7,11,15], 9));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn two_sum(nums: Vec<i32>, target: i32) -> Vec<i32> {
|
|
||||||
let mut components: HashMap<i32, usize> = HashMap::new();
|
|
||||||
for i in 0..nums.len() {
|
|
||||||
let component = target - nums[i];
|
|
||||||
if let Some(j) = components.get(&component) {
|
|
||||||
return vec![i as i32, *j as i32];
|
|
||||||
}
|
|
||||||
components.insert(nums[i], i);
|
|
||||||
}
|
|
||||||
return Vec::new();
|
|
||||||
}
|
|
|
@ -1,46 +0,0 @@
|
||||||
fn main() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_two_numbers(l1: Option<Box<ListNode>>, l2: Option<Box<ListNode>>) -> Option<Box<ListNode>> {
|
|
||||||
let (mut l1, mut l2) = (l1, l2);
|
|
||||||
let mut head = Box::new(ListNode::new(0));
|
|
||||||
let mut tail = &mut head;
|
|
||||||
loop {
|
|
||||||
let mut sum = tail.val;
|
|
||||||
if let Some(node) = &l1 {
|
|
||||||
sum += node.val;
|
|
||||||
l1 = node.next.clone();
|
|
||||||
}
|
|
||||||
if let Some(node) = &l2 {
|
|
||||||
sum += node.val;
|
|
||||||
l2 = node.next.clone();
|
|
||||||
}
|
|
||||||
let next_node = Box::new(ListNode::new(sum / 10));
|
|
||||||
tail.val = sum % 10;
|
|
||||||
if l1.is_none() && l2.is_none() {
|
|
||||||
if next_node.val > 0 { tail.next = Some(next_node); }
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
tail.next = Some(next_node);
|
|
||||||
tail = tail.next.as_mut().unwrap();
|
|
||||||
}
|
|
||||||
return Some(head);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Definition for singly-linked list.
|
|
||||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
|
||||||
pub struct ListNode {
|
|
||||||
pub val: i32,
|
|
||||||
pub next: Option<Box<ListNode>>
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ListNode {
|
|
||||||
#[inline]
|
|
||||||
fn new(val: i32) -> Self {
|
|
||||||
ListNode {
|
|
||||||
next: None,
|
|
||||||
val
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
println!("{}", length_of_longest_substring(String::from("abcabcbb")));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn length_of_longest_substring(s: String) -> i32 {
|
|
||||||
let mut seen: HashMap<char, usize> = HashMap::with_capacity(80);
|
|
||||||
let (mut start_index, mut max_length) = (0usize, 0usize);
|
|
||||||
for (i, c) in s.chars().enumerate() {
|
|
||||||
if let Some(index) = seen.get(&c) {
|
|
||||||
max_length = max_length.max(i - start_index);
|
|
||||||
start_index = *index + 1;
|
|
||||||
seen.retain(|_, i| *i >= start_index);
|
|
||||||
}
|
|
||||||
seen.insert(c, i);
|
|
||||||
}
|
|
||||||
max_length = max_length.max(s.len() - start_index);
|
|
||||||
return max_length as i32;
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
fn main() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: reduce algorithm complexity from O(m+n) to O(log(m+n))
|
|
||||||
pub fn find_median_sorted_arrays(nums1: Vec<i32>, nums2: Vec<i32>) -> f64 {
|
|
||||||
let length = nums1.len() + nums2.len();
|
|
||||||
let mut nums3 = vec![0i32; length];
|
|
||||||
let (mut m, mut n) = (0usize, 0usize);
|
|
||||||
while m + n < length {
|
|
||||||
let x1 = if m < nums1.len() { nums1[m] } else { i32::MAX };
|
|
||||||
let x2 = if n < nums2.len() { nums2[n] } else { i32::MAX };
|
|
||||||
if x1 <= x2 {
|
|
||||||
nums3[m + n] = x1;
|
|
||||||
m += 1;
|
|
||||||
} else {
|
|
||||||
nums3[m + n] = x2;
|
|
||||||
n += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (nums3[(length - 1) / 2] + nums3[length / 2]) as f64 / 2.0;
|
|
||||||
}
|
|
|
@ -1,17 +0,0 @@
|
||||||
fn main() {
|
|
||||||
println!("{}", longest_palindrome(String::from("bb")));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn longest_palindrome(s: String) -> String {
|
|
||||||
let mut max_indexes = (0usize, 1usize);
|
|
||||||
for i in 0..(s.len()-1)*2 {
|
|
||||||
let (mut start, mut end) = (i / 2 + i % 2, i / 2);
|
|
||||||
while start > 0 && end < s.len() - 1 {
|
|
||||||
if s.as_bytes()[start - 1] != s.as_bytes()[end + 1] { break; }
|
|
||||||
start -= 1; end += 1;
|
|
||||||
}
|
|
||||||
let length = end + 1 - start;
|
|
||||||
if length > max_indexes.1 - max_indexes.0 { max_indexes = (start, end + 1); }
|
|
||||||
}
|
|
||||||
return String::from(&s[max_indexes.0..max_indexes.1]);
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
fn main() {
|
|
||||||
println!("{}", convert(String::from("ABC"), 4))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn convert(s: String, num_rows: i32) -> String {
|
|
||||||
if num_rows <= 1 { return s; }
|
|
||||||
let mut result = String::with_capacity(s.len());
|
|
||||||
let num_rows = num_rows as usize;
|
|
||||||
for i in 0..num_rows {
|
|
||||||
for j in (i..s.len()).step_by(num_rows * 2 - 2) {
|
|
||||||
result.push(s.as_bytes()[j] as char);
|
|
||||||
if i > 0 && i < num_rows - 1 {
|
|
||||||
let diagonal_index = j + 2 * (num_rows - i - 1);
|
|
||||||
if diagonal_index >= s.len() { continue; }
|
|
||||||
result.push(s.as_bytes()[diagonal_index] as char);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
fn main() {
|
|
||||||
println!("{}", reverse(1534236469));
|
|
||||||
}
|
|
||||||
|
|
||||||
// problem doesn't allow using 64-bit numbers
|
|
||||||
pub fn reverse(x: i32) -> i32 {
|
|
||||||
let is_negative = x < 0;
|
|
||||||
let (mut x, mut result) = (x.checked_abs().unwrap_or(0), 0i32);
|
|
||||||
while x > 9 {
|
|
||||||
result *= 10;
|
|
||||||
result += x % 10;
|
|
||||||
x /= 10;
|
|
||||||
}
|
|
||||||
return result.checked_mul(10).and_then(|mut n| {
|
|
||||||
n += x % 10;
|
|
||||||
if is_negative { n = -n; }
|
|
||||||
Some(n)
|
|
||||||
}).unwrap_or(0);
|
|
||||||
}
|
|
|
@ -1,21 +0,0 @@
|
||||||
fn main() {
|
|
||||||
println!("{}", my_atoi(String::from("2147483648")));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn my_atoi(s: String) -> i32 {
|
|
||||||
let s = s.trim();
|
|
||||||
let is_neg = s.starts_with('-');
|
|
||||||
let skip_sign = if is_neg || s.starts_with('+') { 1 } else { 0 };
|
|
||||||
let mut result = 0i32;
|
|
||||||
for byte in s.bytes().skip(skip_sign) {
|
|
||||||
if byte < b'0' || byte > b'9' { break; }
|
|
||||||
let digit = (byte - b'0') as i32;
|
|
||||||
if let Some(checked_result) = result.checked_mul(10).and_then(|n| n.checked_add(digit)) {
|
|
||||||
result = checked_result;
|
|
||||||
} else {
|
|
||||||
return if is_neg { i32::MIN } else { i32::MAX };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if is_neg { result = -result; }
|
|
||||||
return result;
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
fn main() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_palindrome(x: i32) -> bool {
|
|
||||||
if x < 0 { return false; }
|
|
||||||
let (mut x_copy, mut reversed) = (x as u32, 0u32);
|
|
||||||
while x_copy > 0 {
|
|
||||||
reversed *= 10;
|
|
||||||
reversed += x_copy % 10;
|
|
||||||
x_copy /= 10;
|
|
||||||
}
|
|
||||||
return reversed == x as u32;
|
|
||||||
}
|
|
16
src/lib.rs
Normal file
16
src/lib.rs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
pub mod p1_two_sum;
|
||||||
|
pub mod p2_add_two_numbers;
|
||||||
|
pub mod p3_longest_substring_without_repeating_characters;
|
||||||
|
pub mod p4_median_of_two_sorted_arrays;
|
||||||
|
pub mod p5_longest_palindrome_substring;
|
||||||
|
pub mod p6_zigzag_conversion;
|
||||||
|
pub mod p7_reverse_integer;
|
||||||
|
pub mod p8_string_to_integer;
|
||||||
|
pub mod p9_palindrome_number;
|
||||||
|
pub mod p10_regular_expression_matching;
|
||||||
|
pub mod p11_container_with_most_water;
|
||||||
|
pub mod p12_integer_to_roman;
|
||||||
|
pub mod p13_roman_to_integer;
|
||||||
|
pub mod p14_longest_common_prefix;
|
||||||
|
pub mod p15_3sum;
|
||||||
|
pub mod p16_3sum_closest;
|
34
src/p10_regular_expression_matching.rs
Normal file
34
src/p10_regular_expression_matching.rs
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
pub struct Solution;
|
||||||
|
impl Solution {
|
||||||
|
pub fn is_match(s: String, p: String) -> bool {
|
||||||
|
let (s, p) = (s.as_bytes(), p.as_bytes());
|
||||||
|
let mut dp = vec![vec![false; p.len() + 1]; s.len() + 1];
|
||||||
|
dp[s.len()][p.len()] = true;
|
||||||
|
for i in (0..=s.len()).rev() {
|
||||||
|
for j in (0..p.len()).rev() {
|
||||||
|
let first_match = i < s.len() && (p[j] == b'.' || p[j] == s[i]);
|
||||||
|
if j + 1 < p.len() && p[j + 1] == b'*' {
|
||||||
|
dp[i][j] = first_match && dp[i + 1][j] || dp[i][j + 2];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
dp[i][j] = first_match && dp[i + 1][j + 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dp[0][0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test1() {
|
||||||
|
assert_eq!(Solution::is_match("aa".to_string(), "a".to_string()), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test2() {
|
||||||
|
assert_eq!(Solution::is_match("aa".to_string(), "a*".to_string()), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test3() {
|
||||||
|
assert_eq!(Solution::is_match("ab".to_string(), ".*".to_string()), true);
|
||||||
|
}
|
29
src/p11_container_with_most_water.rs
Normal file
29
src/p11_container_with_most_water.rs
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
pub struct Solution;
|
||||||
|
impl Solution {
|
||||||
|
pub fn max_area(height: Vec<i32>) -> i32 {
|
||||||
|
let (mut left, mut right) = (0, height.len() - 1);
|
||||||
|
let mut max_water = 0;
|
||||||
|
while left < right {
|
||||||
|
let x = (right - left) as i32; let h;
|
||||||
|
if height[left] < height[right] {
|
||||||
|
h = height[left];
|
||||||
|
left += 1;
|
||||||
|
} else {
|
||||||
|
h = height[right];
|
||||||
|
right -= 1;
|
||||||
|
};
|
||||||
|
max_water = max_water.max(h * x);
|
||||||
|
}
|
||||||
|
return max_water;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test1() {
|
||||||
|
assert_eq!(Solution::max_area(vec![1,8,6,2,5,4,8,3,7]), 49);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test2() {
|
||||||
|
assert_eq!(Solution::max_area(vec![1,1]), 1);
|
||||||
|
}
|
49
src/p12_integer_to_roman.rs
Normal file
49
src/p12_integer_to_roman.rs
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
pub struct Solution;
|
||||||
|
impl Solution {
|
||||||
|
pub fn int_to_roman(num: i32) -> String {
|
||||||
|
let roman_nums = vec!['M', 'D', 'C', 'L', 'X', 'V', 'I'];
|
||||||
|
let mut result = String::with_capacity(15);
|
||||||
|
let (mut num, mut divisor) = (num, 1000);
|
||||||
|
for i in (0..roman_nums.len()).step_by(2) {
|
||||||
|
let roman = roman_nums[i];
|
||||||
|
let roman_amount = num / divisor;
|
||||||
|
match roman_amount {
|
||||||
|
0 => (),
|
||||||
|
1..=3 => {
|
||||||
|
for _ in 0..roman_amount { result.push(roman); }
|
||||||
|
},
|
||||||
|
5..=8 => {
|
||||||
|
let complement = roman_nums[i - 1];
|
||||||
|
result.push(complement);
|
||||||
|
for _ in 0..(roman_amount-5) { result.push(roman); }
|
||||||
|
},
|
||||||
|
4 | 9 => {
|
||||||
|
let complement_index = i - roman_amount as usize / 4;
|
||||||
|
let complement = roman_nums[complement_index];
|
||||||
|
result.push(roman);
|
||||||
|
result.push(complement);
|
||||||
|
},
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
|
num %= divisor;
|
||||||
|
divisor /= 10;
|
||||||
|
}
|
||||||
|
if result.is_empty() { result.push('0'); }
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test1() {
|
||||||
|
assert_eq!(Solution::int_to_roman(3), "III".to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test2() {
|
||||||
|
assert_eq!(Solution::int_to_roman(58), "LVIII".to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test3() {
|
||||||
|
assert_eq!(Solution::int_to_roman(1994), "MCMXCIV".to_string());
|
||||||
|
}
|
27
src/p13_roman_to_integer.rs
Normal file
27
src/p13_roman_to_integer.rs
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
pub struct Solution;
|
||||||
|
impl Solution {
|
||||||
|
pub fn roman_to_int(s: String) -> i32 {
|
||||||
|
s.chars().fold(0, |acc, c| {
|
||||||
|
let num = match c {
|
||||||
|
'M' => 1000, 'D' => 500, 'C' => 100, 'L' => 50,
|
||||||
|
'X' => 10, 'V' => 5, 'I' => 1, _ => 0
|
||||||
|
};
|
||||||
|
acc + num - 2 * (acc % num)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test1() {
|
||||||
|
assert_eq!(Solution::roman_to_int("III".to_string()), 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test2() {
|
||||||
|
assert_eq!(Solution::roman_to_int("LVIII".to_string()), 58);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test3() {
|
||||||
|
assert_eq!(Solution::roman_to_int("MCMXCIV".to_string()), 1994);
|
||||||
|
}
|
30
src/p14_longest_common_prefix.rs
Normal file
30
src/p14_longest_common_prefix.rs
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
pub struct Solution;
|
||||||
|
impl Solution {
|
||||||
|
pub fn longest_common_prefix(strs: Vec<String>) -> String {
|
||||||
|
let mut result = String::with_capacity(200);
|
||||||
|
let first_str = strs[0].as_bytes();
|
||||||
|
if first_str.is_empty() { return result; }
|
||||||
|
for i in 0..first_str.len() {
|
||||||
|
let c = first_str[i];
|
||||||
|
for j in 1..strs.len() {
|
||||||
|
if i >= strs[j].len() || c != strs[j].as_bytes()[i] {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.push(c as char);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test1() {
|
||||||
|
let strs = vec!["flower".to_string(),"flow".to_string(),"flight".to_string()];
|
||||||
|
assert_eq!(Solution::longest_common_prefix(strs), "fl".to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test2() {
|
||||||
|
let strs = vec!["dog".to_string(),"racecar".to_string(),"car".to_string()];
|
||||||
|
assert_eq!(Solution::longest_common_prefix(strs), "".to_string());
|
||||||
|
}
|
43
src/p15_3sum.rs
Normal file
43
src/p15_3sum.rs
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
pub struct Solution;
|
||||||
|
impl Solution {
|
||||||
|
pub fn three_sum(mut nums: Vec<i32>) -> Vec<Vec<i32>> {
|
||||||
|
let mut result = Vec::<Vec<i32>>::new();
|
||||||
|
nums.sort();
|
||||||
|
for i in 0..nums.len()-2 {
|
||||||
|
if i > 0 && nums[i] == nums[i - 1] { continue; }
|
||||||
|
let (mut j, mut k) = (i + 1, nums.len() - 1);
|
||||||
|
while j < k {
|
||||||
|
if j > i + 1 && nums[j - 1] == nums[j] {
|
||||||
|
j += 1; continue;
|
||||||
|
}
|
||||||
|
if k < nums.len() - 1 && nums[k + 1] == nums[k] {
|
||||||
|
k -= 1; continue;
|
||||||
|
}
|
||||||
|
match (nums[i] + nums[j] + nums[k]).cmp(&0) {
|
||||||
|
std::cmp::Ordering::Less => { j += 1; },
|
||||||
|
std::cmp::Ordering::Greater => { k -= 1 },
|
||||||
|
std::cmp::Ordering::Equal => {
|
||||||
|
result.push(vec![nums[i], nums[j], nums[k]]);
|
||||||
|
j += 1; k -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test1() {
|
||||||
|
assert_eq!(Solution::three_sum(vec![-1,0,1,2,-1,-4]), vec![vec![-1,-1,2], vec![-1,0,1]]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test2() {
|
||||||
|
assert_eq!(Solution::three_sum(vec![0,1,1]), Vec::<Vec<i32>>::new());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test3() {
|
||||||
|
assert_eq!(Solution::three_sum(vec![0,0,0]), vec![vec![0,0,0]]);
|
||||||
|
}
|
17
src/p16_3sum_closest.rs
Normal file
17
src/p16_3sum_closest.rs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
pub struct Solution;
|
||||||
|
impl Solution {
|
||||||
|
pub fn three_sum_closest(nums: Vec<i32>, target: i32) -> i32 {
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test1() {
|
||||||
|
assert_eq!(Solution::three_sum_closest(vec![-1,2,1,-4], 1), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test2() {
|
||||||
|
assert_eq!(Solution::three_sum_closest(vec![0,0,0], 1), 0);
|
||||||
|
}
|
35
src/p1_two_sum.rs
Normal file
35
src/p1_two_sum.rs
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
pub struct Solution;
|
||||||
|
impl Solution {
|
||||||
|
pub fn two_sum(nums: Vec<i32>, target: i32) -> Vec<i32> {
|
||||||
|
let mut components: HashMap<i32, usize> = HashMap::new();
|
||||||
|
for i in 0..nums.len() {
|
||||||
|
let component = target - nums[i];
|
||||||
|
if let Some(j) = components.get(&component) {
|
||||||
|
return vec![i as i32, *j as i32];
|
||||||
|
}
|
||||||
|
components.insert(nums[i], i);
|
||||||
|
}
|
||||||
|
return Vec::new();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test1() {
|
||||||
|
let actual = Solution::two_sum(vec![2,7,11,15], 9);
|
||||||
|
assert!(actual == vec![1,0] || actual == vec![0,1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test2() {
|
||||||
|
let actual = Solution::two_sum(vec![3,2,4], 6);
|
||||||
|
assert!(actual == vec![1,2] || actual == vec![2,1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test3() {
|
||||||
|
let actual = Solution::two_sum(vec![3,3], 6);
|
||||||
|
assert!(actual == vec![1,0] || actual == vec![0,1]);
|
||||||
|
}
|
||||||
|
|
50
src/p2_add_two_numbers.rs
Normal file
50
src/p2_add_two_numbers.rs
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
pub struct Solution;
|
||||||
|
impl Solution {
|
||||||
|
pub fn add_two_numbers(l1: Option<Box<ListNode>>, l2: Option<Box<ListNode>>) -> Option<Box<ListNode>> {
|
||||||
|
let (mut l1, mut l2) = (l1, l2);
|
||||||
|
let mut head = Box::new(ListNode::new(0));
|
||||||
|
let mut tail = &mut head;
|
||||||
|
loop {
|
||||||
|
let mut sum = tail.val;
|
||||||
|
if let Some(node) = &l1 {
|
||||||
|
sum += node.val;
|
||||||
|
l1 = node.next.clone();
|
||||||
|
}
|
||||||
|
if let Some(node) = &l2 {
|
||||||
|
sum += node.val;
|
||||||
|
l2 = node.next.clone();
|
||||||
|
}
|
||||||
|
let next_node = Box::new(ListNode::new(sum / 10));
|
||||||
|
tail.val = sum % 10;
|
||||||
|
if l1.is_none() && l2.is_none() {
|
||||||
|
if next_node.val > 0 { tail.next = Some(next_node); }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tail.next = Some(next_node);
|
||||||
|
tail = tail.next.as_mut().unwrap();
|
||||||
|
}
|
||||||
|
return Some(head);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Definition for singly-linked list.
|
||||||
|
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||||
|
pub struct ListNode {
|
||||||
|
pub val: i32,
|
||||||
|
pub next: Option<Box<ListNode>>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ListNode {
|
||||||
|
#[inline]
|
||||||
|
fn new(val: i32) -> Self {
|
||||||
|
ListNode {
|
||||||
|
next: None,
|
||||||
|
val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test() {
|
||||||
|
|
||||||
|
}
|
34
src/p3_longest_substring_without_repeating_characters.rs
Normal file
34
src/p3_longest_substring_without_repeating_characters.rs
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
pub struct Solution;
|
||||||
|
impl Solution {
|
||||||
|
pub fn length_of_longest_substring(s: String) -> i32 {
|
||||||
|
let mut seen: HashMap<char, usize> = HashMap::with_capacity(80);
|
||||||
|
let (mut start_index, mut max_length) = (0usize, 0usize);
|
||||||
|
for (i, c) in s.chars().enumerate() {
|
||||||
|
if let Some(index) = seen.get(&c) {
|
||||||
|
max_length = max_length.max(i - start_index);
|
||||||
|
start_index = *index + 1;
|
||||||
|
seen.retain(|_, i| *i >= start_index);
|
||||||
|
}
|
||||||
|
seen.insert(c, i);
|
||||||
|
}
|
||||||
|
max_length = max_length.max(s.len() - start_index);
|
||||||
|
return max_length as i32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test1() {
|
||||||
|
assert_eq!(Solution::length_of_longest_substring("abcabcbb".to_string()), 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test2() {
|
||||||
|
assert_eq!(Solution::length_of_longest_substring("bbbbb".to_string()), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test3() {
|
||||||
|
assert_eq!(Solution::length_of_longest_substring("pwwkew".to_string()), 3);
|
||||||
|
}
|
31
src/p4_median_of_two_sorted_arrays.rs
Normal file
31
src/p4_median_of_two_sorted_arrays.rs
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
pub struct Solution;
|
||||||
|
impl Solution {
|
||||||
|
// TODO: reduce algorithm complexity from O(m+n) to O(log(m+n))
|
||||||
|
pub fn find_median_sorted_arrays(nums1: Vec<i32>, nums2: Vec<i32>) -> f64 {
|
||||||
|
let length = nums1.len() + nums2.len();
|
||||||
|
let mut nums3 = vec![0i32; length];
|
||||||
|
let (mut m, mut n) = (0usize, 0usize);
|
||||||
|
while m + n < length {
|
||||||
|
let x1 = if m < nums1.len() { nums1[m] } else { i32::MAX };
|
||||||
|
let x2 = if n < nums2.len() { nums2[n] } else { i32::MAX };
|
||||||
|
if x1 <= x2 {
|
||||||
|
nums3[m + n] = x1;
|
||||||
|
m += 1;
|
||||||
|
} else {
|
||||||
|
nums3[m + n] = x2;
|
||||||
|
n += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (nums3[(length - 1) / 2] + nums3[length / 2]) as f64 / 2.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test1() {
|
||||||
|
assert_eq!(Solution::find_median_sorted_arrays(vec![1,3], vec![2]), 2.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test2() {
|
||||||
|
assert_eq!(Solution::find_median_sorted_arrays(vec![1,2], vec![3,4]), 2.5);
|
||||||
|
}
|
27
src/p5_longest_palindrome_substring.rs
Normal file
27
src/p5_longest_palindrome_substring.rs
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
pub struct Solution;
|
||||||
|
impl Solution {
|
||||||
|
pub fn longest_palindrome(s: String) -> String {
|
||||||
|
let mut max_indexes = (0usize, 1usize);
|
||||||
|
for i in 0..(s.len()-1)*2 {
|
||||||
|
let (mut start, mut end) = (i / 2 + i % 2, i / 2);
|
||||||
|
while start > 0 && end < s.len() - 1 {
|
||||||
|
if s.as_bytes()[start - 1] != s.as_bytes()[end + 1] { break; }
|
||||||
|
start -= 1; end += 1;
|
||||||
|
}
|
||||||
|
let length = end + 1 - start;
|
||||||
|
if length > max_indexes.1 - max_indexes.0 { max_indexes = (start, end + 1); }
|
||||||
|
}
|
||||||
|
return String::from(&s[max_indexes.0..max_indexes.1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test1() {
|
||||||
|
let actual = Solution::longest_palindrome("babad".to_string());
|
||||||
|
assert!(actual == "bab".to_string() || actual == "aba".to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test2() {
|
||||||
|
assert_eq!(Solution::longest_palindrome("cbbd".to_string()), "bb".to_string());
|
||||||
|
}
|
34
src/p6_zigzag_conversion.rs
Normal file
34
src/p6_zigzag_conversion.rs
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
pub struct Solution;
|
||||||
|
impl Solution {
|
||||||
|
pub fn convert(s: String, num_rows: i32) -> String {
|
||||||
|
if num_rows <= 1 { return s; }
|
||||||
|
let mut result = String::with_capacity(s.len());
|
||||||
|
let num_rows = num_rows as usize;
|
||||||
|
for i in 0..num_rows {
|
||||||
|
for j in (i..s.len()).step_by(num_rows * 2 - 2) {
|
||||||
|
result.push(s.as_bytes()[j] as char);
|
||||||
|
if i > 0 && i < num_rows - 1 {
|
||||||
|
let diagonal_index = j + 2 * (num_rows - i - 1);
|
||||||
|
if diagonal_index >= s.len() { continue; }
|
||||||
|
result.push(s.as_bytes()[diagonal_index] as char);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test1() {
|
||||||
|
assert_eq!(Solution::convert("PAYPALISHIRING".to_string(), 3), "PAHNAPLSIIGYIR".to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test2() {
|
||||||
|
assert_eq!(Solution::convert("PAYPALISHIRING".to_string(), 4), "PINALSIGYAHRPI".to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test3() {
|
||||||
|
assert_eq!(Solution::convert("A".to_string(), 1), "A".to_string());
|
||||||
|
}
|
33
src/p7_reverse_integer.rs
Normal file
33
src/p7_reverse_integer.rs
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
pub struct Solution;
|
||||||
|
impl Solution {
|
||||||
|
// problem doesn't allow using 64-bit numbers
|
||||||
|
pub fn reverse(x: i32) -> i32 {
|
||||||
|
let is_negative = x < 0;
|
||||||
|
let (mut x, mut result) = (x.checked_abs().unwrap_or(0), 0i32);
|
||||||
|
while x > 9 {
|
||||||
|
result *= 10;
|
||||||
|
result += x % 10;
|
||||||
|
x /= 10;
|
||||||
|
}
|
||||||
|
return result.checked_mul(10).and_then(|mut n| {
|
||||||
|
n += x % 10;
|
||||||
|
if is_negative { n = -n; }
|
||||||
|
Some(n)
|
||||||
|
}).unwrap_or(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test1() {
|
||||||
|
assert_eq!(Solution::reverse(123), 321);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test2() {
|
||||||
|
assert_eq!(Solution::reverse(-123), -321);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test3() {
|
||||||
|
assert_eq!(Solution::reverse(120), 21);
|
||||||
|
}
|
35
src/p8_string_to_integer.rs
Normal file
35
src/p8_string_to_integer.rs
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
pub struct Solution;
|
||||||
|
impl Solution {
|
||||||
|
pub fn my_atoi(s: String) -> i32 {
|
||||||
|
let s = s.trim();
|
||||||
|
let is_neg = s.starts_with('-');
|
||||||
|
let skip_sign = if is_neg || s.starts_with('+') { 1 } else { 0 };
|
||||||
|
let mut result = 0i32;
|
||||||
|
for byte in s.bytes().skip(skip_sign) {
|
||||||
|
if byte < b'0' || byte > b'9' { break; }
|
||||||
|
let digit = (byte - b'0') as i32;
|
||||||
|
if let Some(checked_result) = result.checked_mul(10).and_then(|n| n.checked_add(digit)) {
|
||||||
|
result = checked_result;
|
||||||
|
} else {
|
||||||
|
return if is_neg { i32::MIN } else { i32::MAX };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if is_neg { result = -result; }
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test1() {
|
||||||
|
assert_eq!(Solution::my_atoi("42".to_string()), 42);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test2() {
|
||||||
|
assert_eq!(Solution::my_atoi(" -42".to_string()), -42);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test3() {
|
||||||
|
assert_eq!(Solution::my_atoi("4193 with words".to_string()), 4193);
|
||||||
|
}
|
28
src/p9_palindrome_number.rs
Normal file
28
src/p9_palindrome_number.rs
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
pub struct Solution;
|
||||||
|
impl Solution {
|
||||||
|
pub fn is_palindrome(x: i32) -> bool {
|
||||||
|
if x < 0 { return false; }
|
||||||
|
let (mut x_copy, mut reversed) = (x as u32, 0u32);
|
||||||
|
while x_copy > 0 {
|
||||||
|
reversed *= 10;
|
||||||
|
reversed += x_copy % 10;
|
||||||
|
x_copy /= 10;
|
||||||
|
}
|
||||||
|
return reversed == x as u32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test1() {
|
||||||
|
assert_eq!(Solution::is_palindrome(121), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test2() {
|
||||||
|
assert_eq!(Solution::is_palindrome(-121), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test3() {
|
||||||
|
assert_eq!(Solution::is_palindrome(10), false);
|
||||||
|
}
|
Loading…
Reference in a new issue