回文数是指正读和反读都相同的数字,如121、1331等。在数学和计算机科学中,回文数是一个经典的研究对象,涉及到数论、算法设计等多个领域。在 Exercism 的 “palindrome-products” 练习中,我们需要找到指定范围内两个数乘积为回文数的最小值和最大值。这不仅能帮助我们掌握回文数判断和数学计算技巧,还能深入学习Rust中的数据结构设计和算法优化。
什么是回文数乘积?
回文数乘积问题要求我们在给定的数字范围内,找到两个数的乘积是回文数的情况,并确定其中的最小值和最大值。例如,在范围1-9中:
- 最小回文数乘积是1×1=1
- 最大回文数乘积是3×3=9或1×9=9
回文数乘积在以下领域有应用:
- 数论研究:研究数字的特殊性质
- 算法竞赛:经典的编程挑战题
- 密码学:某些加密算法中使用特殊数字
- 数学娱乐:趣味数学问题
让我们先看看练习提供的结构和函数签名:
#[derive(Debug, PartialEq, Eq)]
pub struct Palindrome {
// implement your palindrome type here
}
impl Palindrome {
pub fn new(a: u64, b: u64) -> Palindrome {
unimplemented!("create a palindrome with factors ({}, {})", a, b)
}
pub fn value(&self) -> u64 {
unimplemented!("return the value of this palindrome")
}
pub fn insert(&mut self, a: u64, b: u64) {
unimplemented!("insert new factors ({}, {}) into this palindrome", a, b)
}
}
pub fn palindrome_products(min: u64, max: u64) -> Option<(Palindrome, Palindrome)> {
unimplemented!(
"Find the min and max palindromic numbers which are products of numbers in the inclusive range ({}..{})",
min,
max
)
}
我们需要实现Palindrome结构体和palindrome_products函数,找到指定范围内回文数乘积的最小值和最大值。
设计分析
1. 核心要求
- 回文数判断:判断一个数是否为回文数
- 因子存储:存储产生回文数的因子对
- 范围搜索:在指定范围内搜索回文数乘积
- 最值查找:找到最小和最大的回文数乘积
2. 技术要点
- 数字处理:高效处理数字的反转和比较
- 数据结构:设计合适的结构体存储回文数和因子
- 算法优化:优化搜索算法以提高效率
- 边界处理:正确处理各种边界情况
完整实现
1. 基础实现
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Palindrome {
value: u64,
factors: Vec<(u64, u64)>,
}
impl Palindrome {
pub fn new(a: u64, b: u64) -> Palindrome {
let value = a * b;
let mut factors = Vec::new();
factors.push((a, b));
Palindrome { value, factors }
}
pub fn value(&self) -> u64 {
self.value
}
pub fn insert(&mut self, a: u64, b: u64) {
// 避免重复添加相同的因子对
if !self.factors.contains(&(a, b)) && !self.factors.contains(&(b, a)) {
self.factors.push((a, b));
}
}
// 获取所有因子对
pub fn factors(&self) -> &[(u64, u64)] {
&self.factors
}
}
pub fn palindrome_products(min: u64, max: u64) -> Option<(Palindrome, Palindrome)> {
// 检查参数有效性
if min > max {
return None;
}
let mut palindromes = Vec::new();
// 遍历所有可能的因子对
for i in min..=max {
for j in i..=max { // j从i开始避免重复计算
let product = i * j;
if is_palindrome(product) {
palindromes.push((product, i, j));
}
}
}
// 如果没有找到回文数乘积
if palindromes.is_empty() {
return None;
}
// 找到最小和最大的回文数
let min_palindrome = palindromes.iter().min_by_key(|&&(value, _, _)| value).unwrap();
let max_palindrome = palindromes.iter().max_by_key(|&&(value, _, _)| value).unwrap();
// 创建Palindrome对象
let mut min_result = Palindrome::new(min_palindrome.1, min_palindrome.2);
let mut max_result = Palindrome::new(max_palindrome.1, max_palindrome.2);
// 添加其他因子对
for &(value, a, b) in &palindromes {
if value == min_result.value() && (a, b) != (min_palindrome.1, min_palindrome.2) {
min_result.insert(a, b);
}
if value == max_result.value() && (a, b) != (max_palindrome.1, max_palindrome.2) {
max_result.insert(a, b);
}
}
Some((min_result, max_result))
}
fn is_palindrome(n: u64) -> bool {
let s = n.to_string();
let chars: Vec<char> = s.chars().collect();
let len = chars.len();
for i in 0..len / 2 {
if chars[i] != chars[len - 1 - i] {
return false;
}
}
true
}
2. 优化实现
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Palindrome {
value: u64,
factors: Vec<(u64, u64)>,
}
impl Palindrome {
pub fn new(a: u64, b: u64) -> Palindrome {
let value = a * b;
let mut factors = Vec::new();
factors.push((a.min(b), a.max(b))); // 标准化因子顺序
Palindrome { value, factors }
}
pub fn value(&self) -> u64 {
self.value
}
pub fn insert(&mut self, a: u64, b: u64) {
let factor_pair = (a.min(b), a.max(b)); // 标准化因子顺序
// 避免重复添加相同的因子对
if !self.factors.contains(&factor_pair) {
self.factors.push(factor_pair);
self.factors.sort(); // 保持因子对有序
}
}
// 获取所有因子对
pub fn factors(&self) -> &[(u64, u64)] {
&self.factors
}
}
pub fn palindrome_products(min: u64, max: u64) -> Option<(Palindrome, Palindrome)> {
// 检查参数有效性
if min > max {
return None;
}
let mut min_palindrome: Option<Palindrome> = None;
let mut max_palindrome: Option<Palindrome> = None;
// 遍历所有可能的因子对
for i in min..=max {
for j in i..=max { // j从i开始避免重复计算
let product = i * j;
if is_palindrome_optimized(product) {
// 更新最小回文数
match min_palindrome.as_mut() {
None => {
min_palindrome = Some(Palindrome::new(i, j));
}
Some(p) => {
if product < p.value() {
min_palindrome = Some(Palindrome::new(i, j));
} else if product == p.value() {
p.insert(i, j);
}
}
}
// 更新最大回文数
match max_palindrome.as_mut() {
None => {
max_palindrome = Some(Palindrome::new(i, j));
}
Some(p) => {
if product > p.value() {
max_palindrome = Some(Palindrome::new(i, j));
} else if product == p.value() {
p.insert(i, j);
}
}
}
}
}
}
// 如果没有找到回文数乘积
match (min_palindrome, max_palindrome) {
(Some(min_p), Some(max_p)) => Some((min_p, max_p)),
_ => None,
}
}
fn is_palindrome_optimized(n: u64) -> bool {
let mut original = n;
let mut reversed = 0;
while original > 0 {
reversed = reversed * 10 + original % 10;
original /= 10;
}
n == reversed
}
3. 高性能实现
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Palindrome {
value: u64,
factors: Vec<(u64, u64)>,
}
impl Palindrome {
pub fn new(a: u64, b: u64) -> Palindrome {
let value = a * b;
let mut factors = vec![(a.min(b), a.max(b))]; // 标准化因子顺序
Palindrome { value, factors }
}
pub fn value(&self) -> u64 {
self.value
}
pub fn insert(&mut self, a: u64, b: u64) {
let factor_pair = (a.min(b), a.max(b)); // 标准化因子顺序
// 使用二分查找避免重复添加相同的因子对
if let Err(pos) = self.factors.binary_search(&factor_pair) {
self.factors.insert(pos, factor_pair);
}
}
// 获取所有因子对
pub fn factors(&self) -> &[(u64, u64)] {
&self.factors
}
}
pub fn palindrome_products(min: u64, max: u64) -> Option<(Palindrome, Palindrome)> {
// 检查参数有效性
if min > max {
return None;
}
let mut min_palindrome: Option<Palindrome> = None;
let mut max_palindrome: Option<Palindrome> = None;
// 遍历所有可能的因子对
for i in min..=max {
// 优化:如果当前最小值已经确定,且i*i大于该值,可以提前结束
if let Some(ref min_p) = min_palindrome {
if i * i > min_p.value() {
break;
}
}
for j in i..=max { // j从i开始避免重复计算
let product = i * j;
// 优化:如果当前最大值已经确定,且product小于该值,跳过
if let Some(ref max_p) = max_palindrome {
if product < max_p.value() {
continue;
}
}
if is_palindrome_fast(product) {
// 更新最小回文数
match min_palindrome.as_mut() {
None => {
min_palindrome = Some(Palindrome::new(i, j));
}
Some(p) => {
match product.cmp(&p.value()) {
std::cmp::Ordering::Less => {
min_palindrome = Some(Palindrome::new(i, j));
}
std::cmp::Ordering::Equal => {
p.insert(i, j);
}
std::cmp::Ordering::Greater => {}
}
}
}
// 更新最大回文数
match max_palindrome.as_mut() {
None => {
max_palindrome = Some(Palindrome::new(i, j));
}
Some(p) => {
match product.cmp(&p.value()) {
std::cmp::Ordering::Greater => {
max_palindrome = Some(Palindrome::new(i, j));
}
std::cmp::Ordering::Equal => {
p.insert(i, j);
}
std::cmp::Ordering::Less => {}
}
}
}
}
}
}
// 如果没有找到回文数乘积
match (min_palindrome, max_palindrome) {
(Some(min_p), Some(max_p)) => Some((min_p, max_p)),
_ => None,
}
}
fn is_palindrome_fast(n: u64) -> bool {
// 特殊情况处理
if n < 10 {
return true;
}
// 计算数字位数
let mut temp = n;
let mut digits = 0;
while temp > 0 {
temp /= 10;
digits += 1;
}
// 获取各位数字
let mut num = n;
let mut digits_vec = Vec::with_capacity(digits);
while num > 0 {
digits_vec.push((num % 10) as u8);
num /= 10;
}
// 检查是否为回文
let len = digits_vec.len();
for i in 0..len / 2 {
if digits_vec[i] != digits_vec[len - 1 - i] {
return false;
}
}
true
}
测试用例分析
通过查看测试用例,我们可以更好地理解需求:
#[test]
/// finds the smallest palindrome from single digit factors
fn test_finds_the_smallest_palindrome_from_single_digit_factors() {
process_smallest_case((1, 9), Some(Palindrome::new(1, 1)));
}
在1-9范围内,最小的回文数乘积是1×1=1。
#[test]
/// finds the largest palindrome from single digit factors
fn test_finds_the_largest_palindrome_from_single_digit_factors() {
let mut expect = Palindrome::new(1, 9);
expect.insert(3, 3);
process_largest_case((1, 9), Some(expect));
}
在1-9范围内,最大的回文数乘积是9(1×9=9或3×3=9)。
#[test]
/// find the smallest palindrome from double digit factors
fn test_find_the_smallest_palindrome_from_double_digit_factors() {
process_smallest_case((10, 99), Some(Palindrome::new(11, 11)));
}
在10-99范围内,最小的回文数乘积是11×11=121。
#[test]
/// find the largest palindrome from double digit factors
fn test_find_the_largest_palindrome_from_double_digit_factors() {
process_largest_case((10, 99), Some(Palindrome::new(91, 99)));
}
在10-99范围内,最大的回文数乘积是91×99=9009。
#[test]
/// empty result for smallest if no palindrome in the range
fn test_empty_result_for_smallest_if_no_palindrome_in_the_range() {
process_smallest_case((1002, 1003), None);
}
在1002-1003范围内没有回文数乘积,应返回None。
#[test]
/// error result for smallest if min is more than max
fn test_error_result_for_smallest_if_min_is_more_than_max() {
process_smallest_case((10000, 1), None);
}
当min大于max时,应返回None。
性能优化版本
考虑性能的优化实现:
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Palindrome {
value: u64,
factors: Vec<(u64, u64)>,
}
impl Palindrome {
pub fn new(a: u64, b: u64) -> Palindrome {
let value = a * b;
let mut factors = vec![(a.min(b), a.max(b))]; // 标准化因子顺序
Palindrome { value, factors }
}
pub fn value(&self) -> u64 {
self.value
}
pub fn insert(&mut self, a: u64, b: u64) {
let factor_pair = (a.min(b), a.max(b)); // 标准化因子顺序
// 使用二分查找避免重复添加相同的因子对
if let Err(pos) = self.factors.binary_search(&factor_pair) {
self.factors.insert(pos, factor_pair);
}
}
// 获取所有因子对
pub fn factors(&self) -> &[(u64, u64)] {
&self.factors
}
}
pub fn palindrome_products(min: u64, max: u64) -> Option<(Palindrome, Palindrome)> {
// 检查参数有效性
if min > max {
return None;
}
let mut min_palindrome: Option<Palindrome> = None;
let mut max_palindrome: Option<Palindrome> = None;
// 从两端向中间搜索,提高找到极值的效率
let range: Vec<u64> = (min..=max).collect();
let len = range.len();
for i in 0..len {
let a = range[i];
// 优化:提前终止条件
if let Some(ref min_p) = min_palindrome {
if a * a > min_p.value() {
break;
}
}
for j in i..len {
let b = range[j];
let product = a * b;
// 优化:跳过不可能成为最值的乘积
let should_check = match (&min_palindrome, &max_palindrome) {
(Some(min_p), Some(max_p)) => {
product >= min_p.value() && product <= max_p.value()
}
(Some(min_p), None) => product >= min_p.value(),
(None, Some(max_p)) => product <= max_p.value(),
(None, None) => true,
};
if should_check && is_palindrome_ultra_fast(product) {
// 更新最小回文数
match min_palindrome.as_mut() {
None => {
min_palindrome = Some(Palindrome::new(a, b));
}
Some(p) => {
match product.cmp(&p.value()) {
std::cmp::Ordering::Less => {
min_palindrome = Some(Palindrome::new(a, b));
}
std::cmp::Ordering::Equal => {
p.insert(a, b);
}
std::cmp::Ordering::Greater => {}
}
}
}
// 更新最大回文数
match max_palindrome.as_mut() {
None => {
max_palindrome = Some(Palindrome::new(a, b));
}
Some(p) => {
match product.cmp(&p.value()) {
std::cmp::Ordering::Greater => {
max_palindrome = Some(Palindrome::new(a, b));
}
std::cmp::Ordering::Equal => {
p.insert(a, b);
}
std::cmp::Ordering::Less => {}
}
}
}
}
}
}
// 如果没有找到回文数乘积
match (min_palindrome, max_palindrome) {
(Some(min_p), Some(max_p)) => Some((min_p, max_p)),
_ => None,
}
}
fn is_palindrome_ultra_fast(n: u64) -> bool {
// 对于小数字使用查表法
if n < 10 {
return true;
}
// 使用数学方法反转数字
let original = n;
let mut reversed = 0;
let mut temp = n;
while temp > 0 {
reversed = reversed * 10 + temp % 10;
temp /= 10;
}
original == reversed
}
// 使用字符串的高性能版本
fn is_palindrome_string_fast(n: u64) -> bool {
let s = n.to_string();
let bytes = s.as_bytes();
let len = bytes.len();
for i in 0..len / 2 {
if bytes[i] != bytes[len - 1 - i] {
return false;
}
}
true
}
错误处理和边界情况
考虑更多边界情况的实现:
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Palindrome {
value: u64,
factors: Vec<(u64, u64)>,
}
impl Palindrome {
pub fn new(a: u64, b: u64) -> Palindrome {
let value = a * b;
let mut factors = vec![(a.min(b), a.max(b))]; // 标准化因子顺序
Palindrome { value, factors }
}
pub fn value(&self) -> u64 {
self.value
}
pub fn insert(&mut self, a: u64, b: u64) {
let factor_pair = (a.min(b), a.max(b)); // 标准化因子顺序
// 使用二分查找避免重复添加相同的因子对
if let Err(pos) = self.factors.binary_search(&factor_pair) {
self.factors.insert(pos, factor_pair);
}
}
// 获取所有因子对
pub fn factors(&self) -> &[(u64, u64)] {
&self.factors
}
// 检查是否包含特定因子对
pub fn has_factors(&self, a: u64, b: u64) -> bool {
let factor_pair = (a.min(b), a.max(b));
self.factors.contains(&factor_pair)
}
}
#[derive(Debug, PartialEq)]
pub enum PalindromeError {
InvalidRange,
NoPalindromesFound,
}
impl std::fmt::Display for PalindromeError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
PalindromeError::InvalidRange => write!(f, "无效的范围"),
PalindromeError::NoPalindromesFound => write!(f, "未找到回文数"),
}
}
}
impl std::error::Error for PalindromeError {}
pub fn palindrome_products_safe(min: u64, max: u64) -> Result<(Palindrome, Palindrome), PalindromeError> {
// 检查参数有效性
if min > max {
return Err(PalindromeError::InvalidRange);
}
let mut min_palindrome: Option<Palindrome> = None;
let mut max_palindrome: Option<Palindrome> = None;
// 遍历所有可能的因子对
for i in min..=max {
for j in i..=max { // j从i开始避免重复计算
let product = i * j;
if is_palindrome_with_cache(product) {
// 更新最小回文数
match min_palindrome.as_mut() {
None => {
min_palindrome = Some(Palindrome::new(i, j));
}
Some(p) => {
match product.cmp(&p.value()) {
std::cmp::Ordering::Less => {
min_palindrome = Some(Palindrome::new(i, j));
}
std::cmp::Ordering::Equal => {
p.insert(i, j);
}
std::cmp::Ordering::Greater => {}
}
}
}
// 更新最大回文数
match max_palindrome.as_mut() {
None => {
max_palindrome = Some(Palindrome::new(i, j));
}
Some(p) => {
match product.cmp(&p.value()) {
std::cmp::Ordering::Greater => {
max_palindrome = Some(Palindrome::new(i, j));
}
std::cmp::Ordering::Equal => {
p.insert(i, j);
}
std::cmp::Ordering::Less => {}
}
}
}
}
}
}
// 如果没有找到回文数乘积
match (min_palindrome, max_palindrome) {
(Some(min_p), Some(max_p)) => Ok((min_p, max_p)),
_ => Err(PalindromeError::NoPalindromesFound),
}
}
pub fn palindrome_products(min: u64, max: u64) -> Option<(Palindrome, Palindrome)> {
palindrome_products_safe(min, max).ok()
}
use std::collections::HashMap;
use std::sync::Mutex;
use once_cell::sync::Lazy;
static PALINDROME_CACHE: Lazy<Mutex<HashMap<u64, bool>>> = Lazy::new(|| Mutex::new(HashMap::new()));
fn is_palindrome_with_cache(n: u64) -> bool {
{
let cache = PALINDROME_CACHE.lock().unwrap();
if let Some(&result) = cache.get(&n) {
return result;
}
}
let result = is_palindrome_optimized(n);
let mut cache = PALINDROME_CACHE.lock().unwrap();
cache.insert(n, result);
result
}
fn is_palindrome_optimized(n: u64) -> bool {
let original = n;
let mut reversed = 0;
let mut temp = n;
while temp > 0 {
reversed = reversed * 10 + temp % 10;
temp /= 10;
}
original == reversed
}
扩展功能
基于基础实现,我们可以添加更多功能:
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Palindrome {
value: u64,
factors: Vec<(u64, u64)>,
}
impl Palindrome {
pub fn new(a: u64, b: u64) -> Palindrome {
let value = a * b;
let mut factors = vec![(a.min(b), a.max(b))]; // 标准化因子顺序
Palindrome { value, factors }
}
pub fn value(&self) -> u64 {
self.value
}
pub fn insert(&mut self, a: u64, b: u64) {
let factor_pair = (a.min(b), a.max(b)); // 标准化因子顺序
// 使用二分查找避免重复添加相同的因子对
if let Err(pos) = self.factors.binary_search(&factor_pair) {
self.factors.insert(pos, factor_pair);
}
}
// 获取所有因子对
pub fn factors(&self) -> &[(u64, u64)] {
&self.factors
}
// 获取因子对数量
pub fn factor_count(&self) -> usize {
self.factors.len()
}
// 检查是否为质数回文
pub fn is_prime_palindrome(&self) -> bool {
is_prime(self.value)
}
}
pub struct PalindromeAnalyzer {
min_factor: u64,
max_factor: u64,
palindromes: Vec<Palindrome>,
}
impl PalindromeAnalyzer {
pub fn new(min: u64, max: u64) -> Option<Self> {
if min > max {
return None;
}
let mut analyzer = PalindromeAnalyzer {
min_factor: min,
max_factor: max,
palindromes: Vec::new(),
};
analyzer.find_all_palindromes();
Some(analyzer)
}
fn find_all_palindromes(&mut self) {
let mut palindrome_map: std::collections::HashMap<u64, Vec<(u64, u64)>> = std::collections::HashMap::new();
// 遍历所有可能的因子对
for i in self.min_factor..=self.max_factor {
for j in i..=self.max_factor {
let product = i * j;
if is_palindrome(product) {
palindrome_map.entry(product).or_insert_with(Vec::new).push((i, j));
}
}
}
// 创建Palindrome对象
for (value, factors) in palindrome_map {
if let Some((first_a, first_b)) = factors.first() {
let mut palindrome = Palindrome::new(*first_a, *first_b);
for (a, b) in factors.iter().skip(1) {
palindrome.insert(*a, *b);
}
self.palindromes.push(palindrome);
}
}
// 按值排序
self.palindromes.sort_by_key(|p| p.value());
}
// 获取所有回文数
pub fn all_palindromes(&self) -> &[Palindrome] {
&self.palindromes
}
// 获取最小回文数
pub fn min_palindrome(&self) -> Option<&Palindrome> {
self.palindromes.first()
}
// 获取最大回文数
pub fn max_palindrome(&self) -> Option<&Palindrome> {
self.palindromes.last()
}
// 获取指定范围内的回文数
pub fn palindromes_in_range(&self, min_val: u64, max_val: u64) -> Vec<&Palindrome> {
self.palindromes
.iter()
.filter(|p| p.value() >= min_val && p.value() <= max_val)
.collect()
}
// 统计信息
pub fn statistics(&self) -> PalindromeStatistics {
let total_count = self.palindromes.len();
let min_value = self.palindromes.first().map(|p| p.value()).unwrap_or(0);
let max_value = self.palindromes.last().map(|p| p.value()).unwrap_or(0);
let prime_palindromes = self.palindromes.iter().filter(|p| p.is_prime_palindrome()).count();
let avg_factors: f64 = if !self.palindromes.is_empty() {
self.palindromes.iter().map(|p| p.factor_count()).sum::<usize>() as f64
/ self.palindromes.len() as f64
} else {
0.0
};
PalindromeStatistics {
total_count,
min_value,
max_value,
prime_palindromes,
average_factors_per_palindrome: avg_factors,
}
}
}
#[derive(Debug)]
pub struct PalindromeStatistics {
pub total_count: usize,
pub min_value: u64,
pub max_value: u64,
pub prime_palindromes: usize,
pub average_factors_per_palindrome: f64,
}
pub fn palindrome_products(min: u64, max: u64) -> Option<(Palindrome, Palindrome)> {
let analyzer = PalindromeAnalyzer::new(min, max)?;
let min_palindrome = analyzer.min_palindrome()?.clone();
let max_palindrome = analyzer.max_palindrome()?.clone();
Some((min_palindrome, max_palindrome))
}
fn is_palindrome(n: u64) -> bool {
let original = n;
let mut reversed = 0;
let mut temp = n;
while temp > 0 {
reversed = reversed * 10 + temp % 10;
temp /= 10;
}
original == reversed
}
fn is_prime(n: u64) -> bool {
if n < 2 {
return false;
}
if n == 2 || n == 3 {
return true;
}
if n % 2 == 0 || n % 3 == 0 {
return false;
}
let limit = (n as f64).sqrt() as u64;
let mut i = 5;
while i <= limit {
if n % i == 0 || n % (i + 2) == 0 {
return false;
}
i += 6;
}
true
}
// 便利函数
pub fn find_all_palindromes(min: u64, max: u64) -> Option<Vec<Palindrome>> {
let analyzer = PalindromeAnalyzer::new(min, max)?;
Some(analyzer.all_palindromes().to_vec())
}
实际应用场景
回文数乘积在实际开发中有以下应用:
- 算法竞赛:经典的编程挑战题
- 数论研究:研究数字的特殊性质
- 密码学:某些加密算法中使用特殊数字
- 数学娱乐:趣味数学问题
- 教育工具:编程教学示例
- 性能测试:算法优化练习
- 数据分析:特殊数字模式识别
算法复杂度分析
-
时间复杂度:O(n²×log(m))
- 其中n是范围大小,m是乘积的位数
- 需要检查O(n²)个因子对,每个回文数判断需要O(log(m))时间
-
空间复杂度:O(k)
- 其中k是找到的回文数数量
- 需要存储找到的回文数及其因子对
与其他实现方式的比较
// 使用函数式编程的实现
pub fn palindrome_products_functional(min: u64, max: u64) -> Option<(Palindrome, Palindrome)> {
if min > max {
return None;
}
let palindromes: Vec<_> = (min..=max)
.flat_map(|i| {
(i..=max).map(move |j| (i * j, i, j))
})
.filter(|&(product, _, _)| is_palindrome(product))
.collect();
if palindromes.is_empty() {
return None;
}
let min_entry = palindromes.iter().min_by_key(|&&(value, _, _)| value).unwrap();
let max_entry = palindromes.iter().max_by_key(|&&(value, _, _)| value).unwrap();
let mut min_palindrome = Palindrome::new(min_entry.1, min_entry.2);
let mut max_palindrome = Palindrome::new(max_entry.1, max_entry.2);
for &(value, a, b) in &palindromes {
if value == min_palindrome.value() && (a, b) != (min_entry.1, min_entry.2) {
min_palindrome.insert(a, b);
}
if value == max_palindrome.value() && (a, b) != (max_entry.1, max_entry.2) {
max_palindrome.insert(a, b);
}
}
Some((min_palindrome, max_palindrome))
}
// 使用并行计算的实现
use rayon::prelude::*;
pub fn palindrome_products_parallel(min: u64, max: u64) -> Option<(Palindrome, Palindrome)> {
if min > max {
return None;
}
let range: Vec<u64> = (min..=max).collect();
let palindromes: Vec<_> = range
.par_iter()
.flat_map(|&i| {
range.par_iter().filter(move |&&j| j >= i).map(move |&j| (i * j, i, j))
})
.filter(|&(product, _, _)| is_palindrome(product))
.collect();
if palindromes.is_empty() {
return None;
}
let min_entry = palindromes.iter().min_by_key(|&&(value, _, _)| value).unwrap();
let max_entry = palindromes.iter().max_by_key(|&&(value, _, _)| value).unwrap();
let mut min_palindrome = Palindrome::new(min_entry.1, min_entry.2);
let mut max_palindrome = Palindrome::new(max_entry.1, max_entry.2);
for &(value, a, b) in &palindromes {
if value == min_palindrome.value() && (a, b) != (min_entry.1, min_entry.2) {
min_palindrome.insert(a, b);
}
if value == max_palindrome.value() && (a, b) != (max_entry.1, max_entry.2) {
max_palindrome.insert(a, b);
}
}
Some((min_palindrome, max_palindrome))
}
// 使用生成器模式的实现
pub struct PalindromeGenerator {
min: u64,
max: u64,
current_i: u64,
current_j: u64,
}
impl PalindromeGenerator {
pub fn new(min: u64, max: u64) -> Self {
PalindromeGenerator {
min,
max,
current_i: min,
current_j: min,
}
}
}
impl Iterator for PalindromeGenerator {
type Item = (u64, u64, u64); // (product, factor1, factor2)
fn next(&mut self) -> Option<Self::Item> {
if self.current_i > self.max {
return None;
}
let product = self.current_i * self.current_j;
let result = (product, self.current_i, self.current_j);
// 移动到下一个因子对
self.current_j += 1;
if self.current_j > self.max {
self.current_i += 1;
self.current_j = self.current_i;
}
if is_palindrome(result.0) {
Some(result)
} else {
self.next() // 递归查找下一个回文数
}
}
}
// 使用第三方库的实现
// [dependencies]
// num = "0.4"
use num::bigint::BigUint;
pub fn palindrome_products_big(min: u64, max: u64) -> Option<(Palindrome, Palindrome)> {
let min_big = BigUint::from(min);
let max_big = BigUint::from(max);
if min_big > max_big {
return None;
}
// 实现大数版本的回文数查找
// 适用于超大数范围
unimplemented!()
}
总结
通过 palindrome-products 练习,我们学到了:
- 回文数判断:掌握了多种判断回文数的方法
- 算法优化:学会了优化搜索算法以提高效率
- 数据结构设计:理解了如何设计合适的数据结构存储复杂信息
- 边界处理:深入理解了各种边界情况的处理
- 性能考虑:了解了不同实现方式的性能特点
- 错误处理:学会了使用Result类型处理可能的错误
这些技能在实际开发中非常有用,特别是在算法设计、数学计算、性能优化等场景中。回文数乘积虽然是一个具体的数学问题,但它涉及到了算法优化、数据结构设计、边界处理等许多核心概念,是学习Rust实用编程的良好起点。
通过这个练习,我们也看到了Rust在数学计算和算法实现方面的强大能力,以及如何用安全且高效的方式实现经典算法。这种结合了安全性和性能的语言特性正是Rust的魅力所在。
15万+

被折叠的 条评论
为什么被折叠?



