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