diff --git a/Cargo.lock b/Cargo.lock index 12ffe3d..2b70ee4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -16,6 +16,10 @@ version = "0.1.0" name = "kth_largest" version = "0.1.0" +[[package]] +name = "longest_palindromic_substring" +version = "0.1.0" + [[package]] name = "merge_sorted_array" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 257da6a..5b44961 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,4 +9,5 @@ members = [ "implement_queue_using_stacks", "merge_sorted_array", "intersection_of_two_arrays", + "longest_palindromic_substring", ] diff --git a/README.md b/README.md index 4a6e6f2..9c27bd7 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ Resolving problems of LeetCode in RustLang. ## Solutions * [1. Two Sum](./two_sum/src/lib.rs) +* [5. Longest Palindromic Substring](./longest_palindromic_substring/lib.rs) * [7. Reverse Integer](./reverse_integer/src/lib.rs) * [15. 3 Sum](./three_sum/src/lib.rs) * [88. Merge Sorted Array](./merge_sorted_array/src/lib.rs) @@ -25,3 +26,5 @@ cargo doc --open -p ## References * [LeetcodeTop](https://github.com/afatcoder/LeetcodeTop): Top Hit Leetcode problems in interviews. +* [The Algorithms - Rust](https://github.com/TheAlgorithms/Rust) +* [LeetCode Cookbook](https://books.halfrost.com/leetcode/) diff --git a/longest_palindromic_substring/Cargo.toml b/longest_palindromic_substring/Cargo.toml new file mode 100644 index 0000000..e536413 --- /dev/null +++ b/longest_palindromic_substring/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "longest_palindromic_substring" +version = "0.1.0" +authors = ["Ryan Li "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/longest_palindromic_substring/src/lib.rs b/longest_palindromic_substring/src/lib.rs new file mode 100644 index 0000000..c7929ac --- /dev/null +++ b/longest_palindromic_substring/src/lib.rs @@ -0,0 +1,126 @@ +/*! + * # 5. Longest Palindromic Substring + * + * [Problem link](https://leetcode.com/problems/longest-palindromic-substring/) + */ + +#![allow(dead_code)] + +struct Solution {} + +// ---------------------------------------------------------------------------- + +impl Solution { + pub fn longest_palindrome(s: String) -> String { + if s.len() < 2 { + return s; + } + let chars: Vec = s.chars().collect(); + let odd_longest: String = { + let mut longest_part = vec![]; + for (i, &c) in chars.iter().enumerate() { + let mut current_part = vec![c]; + let (mut low, mut high) = (i, i); + loop { + if chars[low] != chars[high] { + // not a palindrome + break; + } + if low != high { + // exclude the condition only one char + current_part.push(chars[low]); + } + if low > 0 && high < chars.len() - 1 { + low -= 1; + high += 1; + } else { + break; + } + } + if current_part.len() > longest_part.len() { + longest_part = current_part; + } + } + let left_part = longest_part[1..] + .iter() + .rev() + .cloned() + .collect::>(); + [left_part, longest_part].concat().iter().cloned().collect() + }; + let even_longest: String = { + let mut longest_part = vec![]; + for (i, _) in chars[..chars.len() - 1].iter().enumerate() { + let mut current_part = vec![]; + let (mut low, mut high) = (i, i + 1); + loop { + if chars[low] == chars[high] { + current_part.push(chars[high]); + } else { + break; + } + if low > 0 && high < chars.len() - 1 { + low -= 1; + high += 1; + } else { + break; + } + } + if current_part.len() > longest_part.len() { + longest_part = current_part; + } + } + let left_part = longest_part.iter().rev().cloned().collect::>(); + [left_part, longest_part].concat().iter().cloned().collect() + }; + if odd_longest.len() > even_longest.len() { + odd_longest + } else { + even_longest + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn accepted(input: String, expected: Vec) { + assert!(expected.contains(&Solution::longest_palindrome(input))); + } + + #[test] + fn test_example_1() { + let input = "babad".to_string(); + let expected = vec!["bab".to_string(), "aba".to_string()]; + accepted(input, expected); + } + + #[test] + fn test_example_2() { + let input = "cbbd".to_string(); + let expected = vec!["bb".to_string()]; + accepted(input, expected); + } + + #[test] + fn test_empty_string() { + let input = "".to_string(); + let expected = vec!["".to_string()]; + accepted(input, expected); + } + + #[test] + fn test_one_string() { + let input = "a".to_string(); + let expected = vec!["a".to_string()]; + accepted(input, expected); + } + + #[test] + fn test_two_string() { + let input = "bb".to_string(); + let expected = vec!["bb".to_string()]; + accepted(input, expected); + } +}