Moved every rust file from src/bin to src, added tests for each problem, added lib.rs file

This commit is contained in:
Egor 2024-04-23 04:21:09 +03:00
parent 955182542e
commit cede8e5f45
33 changed files with 552 additions and 342 deletions

View file

@ -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];
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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)
})
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -1,8 +0,0 @@
fn main() {
}
pub fn three_sum_closest(nums: Vec<i32>, target: i32) -> i32 {
return 0;
}

View file

@ -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();
}

View file

@ -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
}
}
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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]);
}

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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
View 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;

View 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);
}

View 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);
}

View 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());
}

View 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);
}

View 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
View 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
View 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
View 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
View 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() {
}

View 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);
}

View 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);
}

View 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());
}

View 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
View 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);
}

View 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);
}

View 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);
}