一些Rust基础数学算法
🌗

一些Rust基础数学算法

Author
Tags
rust
算法
因数

因数/质因数算法

找出n的因数

 
一半(小)
fn factor(n: usize) -> Vec<usize> {
    (1..).take_while(|i| i * i <= n)
        .filter(|x| n%x ==0)
        .collect::<Vec<usize>>()
}
全部
fn factor_full(n: usize) -> Vec<(usize,usize)> {
    (1..).take_while(|i| i * i <= n)
        .filter(|x| n%x ==0)
        .map(|x| (x, n/x))
        .collect::<Vec<(usize,usize)>>()
}

求n的质因数序列

fn factor_primes(n: usize) -> Vec<usize> {
    let mut a = 2;
    let mut m = n;
    let mut result = Vec::new();
    for i in a..=m {
        while n != i {
            if m % i == 0 {
                let t: usize = *result.last().unwrap_or(&0);
                if t != i {
                    result.push(i);
                }
                m = m / i
            } else {
                break;
            }
        }
    }
		if result.len() == 0 {
        return vec![1,n];
    }

    result
}

分解质因数 算法同上

fn factor_primes(n: usize) -> Vec<usize> {
    let mut a = 2;
    let mut m = n;
    let mut result = Vec::new();
    for i in a..=m {
        while n != i {
            if m % i == 0 {
                result.push(i);
                m = m / i
            } else {
                break;
            }
        }
    }
    
    if result.len() == 0 {
        return vec![1,n];
    }

    result
}

参考链接

 

素数算法

找出n内的素数

use std::collections::HashMap;

fn find_primes(n: usize) -> Vec<usize> {
    let mut result = Vec::new();
    let mut is_prime = HashMap::new();
    is_prime.insert(2, true);
    is_prime.insert(3, true);
    is_prime.insert(5, true);
    is_prime.insert(7, true);

    for i in 2..=n {
        let is_pr = is_prime.entry(i).or_insert(true);
        if *is_pr {
            result.push(i);
        }

        ((i * 2)..=n).step_by(i).for_each(|x| {
            is_prime.entry(x).or_insert(false);
        });
    }

    result
}
 

vec版本, 实测速度更快, 空间略大

fn find_primes(n: usize) -> Vec<usize> {
    let mut result = Vec::new();
    let mut is_prime = vec![true; n + 1];

    for i in 2..=n {
        if is_prime[i] {
            result.push(i);
        }

        ((i * 2)..=n).step_by(i).for_each(|x| {
            is_prime[x] = false;
        });
    }

    result
}
 

参考链接

 

线性筛选法

fn find_primes(n: usize) -> Vec<usize> {
    let mut result = vec![0; n + 1];
    let mut is_prime = vec![true; n + 1];
    let mut count = 0;
    for i in 2..=n {
        if is_prime[i] {
            result[count] = i;
            count += 1;
        }

        let mut j = 0;
        while result[j] * i <= n {
            is_prime[result[j] * i] = false;
            if (i % result[j]) == 0 {
                break;
            }
            j += 1;
        }
    }

    result.retain(|x| *x != 0);
    result
}

参考链接

 
 

其它算法

判断n是否为完全平方数

 
牛顿法
fn is_perfect_square(num:usize) ->bool {
    let mut x = num;
    while (x * x) > num {
        x = (x + num / x)/2;
    }
    return x * x == num;
}

参考链接

Leetcode 367: Valid Perfect Square
给你一个正整数num,写一个函数来判断如果num是完全平方数,则返回True,反之则返回False。 注意: 不要使用任何的内置函数比如 sqrt 。 例子1: 输入: 16返回: True 例子2: 输入: 14输出: False 这个题目很简单,就是判断一下一个数是否是完全平方数。 我最开始的思路是,从1开始到num,依次判断每个数的平方是否等于num,若大于num,则直接退出返回False。但是这样会存在溢出的情况,且运算速度较慢。 我们可以采用二分法来改善时间复杂度。同时我们可以找出在int范围内的最大的平方根,为46340。然后我们再来进行判断。具体代码如下: 下面我们来介绍第二种方法,首先我们来看一个数列,1,3, 5,7...2n -1。根据等差数列求和我们可以得到这个数列的和为 。所以我们可以得出一个完全平方数可以写成1+3+5+7... 根据上面的结论,我们可以让num一直减奇数数列,看最后是否为0。具体如下: 除了上面的两种方法,我们还可以使用 牛顿法,具体牛顿法,大家可以去看一些博客或者看wiki,主要就是切线逼近的思想,将 转化为 的方式来求解,利用切线一直逼近方程的解。 具体代码如下: 这个题目比较简单,但是方法较多,涉及一些数论知识和数学方法,所以关于常见的一些数学知识和结论要掌握,这样遇到题目,就可以很快的做出来。 欢迎大家交流,点赞的人运气都不会差~~
Leetcode 367: Valid Perfect Square
 

最大公约数 & 最小公倍数

fn gcd(a: i64, b: i64) -> i64 { if b == 0 { a } else { gcd(b, a % b)} }
fn lcm(a: i64, b: i64) -> i64 { a / gcd(a, b) * b }