Rust 练习册 :Palindrome Products与回文数

回文数是指正读和反读都相同的数字,如121、1331等。在数学和计算机科学中,回文数是一个经典的研究对象,涉及到数论、算法设计等多个领域。在 Exercism 的 “palindrome-products” 练习中,我们需要找到指定范围内两个数乘积为回文数的最小值和最大值。这不仅能帮助我们掌握回文数判断和数学计算技巧,还能深入学习Rust中的数据结构设计和算法优化。

什么是回文数乘积?

回文数乘积问题要求我们在给定的数字范围内,找到两个数的乘积是回文数的情况,并确定其中的最小值和最大值。例如,在范围1-9中:

  • 最小回文数乘积是1×1=1
  • 最大回文数乘积是3×3=9或1×9=9

回文数乘积在以下领域有应用:

  1. 数论研究:研究数字的特殊性质
  2. 算法竞赛:经典的编程挑战题
  3. 密码学:某些加密算法中使用特殊数字
  4. 数学娱乐:趣味数学问题

让我们先看看练习提供的结构和函数签名:

#[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. 核心要求

  1. 回文数判断:判断一个数是否为回文数
  2. 因子存储:存储产生回文数的因子对
  3. 范围搜索:在指定范围内搜索回文数乘积
  4. 最值查找:找到最小和最大的回文数乘积

2. 技术要点

  1. 数字处理:高效处理数字的反转和比较
  2. 数据结构:设计合适的结构体存储回文数和因子
  3. 算法优化:优化搜索算法以提高效率
  4. 边界处理:正确处理各种边界情况

完整实现

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

实际应用场景

回文数乘积在实际开发中有以下应用:

  1. 算法竞赛:经典的编程挑战题
  2. 数论研究:研究数字的特殊性质
  3. 密码学:某些加密算法中使用特殊数字
  4. 数学娱乐:趣味数学问题
  5. 教育工具:编程教学示例
  6. 性能测试:算法优化练习
  7. 数据分析:特殊数字模式识别

算法复杂度分析

  1. 时间复杂度:O(n²×log(m))

    • 其中n是范围大小,m是乘积的位数
    • 需要检查O(n²)个因子对,每个回文数判断需要O(log(m))时间
  2. 空间复杂度: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 练习,我们学到了:

  1. 回文数判断:掌握了多种判断回文数的方法
  2. 算法优化:学会了优化搜索算法以提高效率
  3. 数据结构设计:理解了如何设计合适的数据结构存储复杂信息
  4. 边界处理:深入理解了各种边界情况的处理
  5. 性能考虑:了解了不同实现方式的性能特点
  6. 错误处理:学会了使用Result类型处理可能的错误

这些技能在实际开发中非常有用,特别是在算法设计、数学计算、性能优化等场景中。回文数乘积虽然是一个具体的数学问题,但它涉及到了算法优化、数据结构设计、边界处理等许多核心概念,是学习Rust实用编程的良好起点。

通过这个练习,我们也看到了Rust在数学计算和算法实现方面的强大能力,以及如何用安全且高效的方式实现经典算法。这种结合了安全性和性能的语言特性正是Rust的魅力所在。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值