Skip to main content

四、数学算法

高考考点

数学算法:最值、均值、公约数、素数、累加、累乘、阶乘、回文数、斐波那契数列;

一、 最值(最大值/最小值)

1. 是什么

从一组数值中筛选出最大的数(最大值)最小的数(最小值),是最基础的数学统计操作,无需复杂逻辑,遍历比对即可实现。

2. C# 代码实现

using System;

class MaxMinWithoutTuple
{
static void Main(string[] args)
{
// 测试空数组
int[] emptyNums = null;
int maxValue;
int minValue;

GetMaxAndMinWithOut(emptyNums, out maxValue, out minValue);

Console.WriteLine($"数组最大值:{maxValue},最小值:{minValue}");

// 测试正常数组
int[] normalNums = { 5, 2, 9, 1, 7, 4 };
GetMaxAndMinWithOut(normalNums, out maxValue, out minValue);
Console.WriteLine($"正常数组最大值:{maxValue},最小值:{minValue}");
}

static void GetMaxAndMinWithOut(int[] nums, out int max, out int min)
{
// 处理数组为空或 null 的情况(不抛异常,赋默认值+友好提示)
if (nums == null || nums.Length == 0)
{
Console.WriteLine("【提示】数组为空或无效,无法获取最值,返回默认值 0");
// 必须给 out 参数赋值,否则编译失败,这里赋默认值 0
max = 0;
min = 0;
return; // 直接返回,不再执行后续逻辑
}

// 正常逻辑:遍历获取最值
max = nums[0];
min = nums[0];
foreach (int num in nums)
{
if (num > max) max = num;
if (num < min) min = num;
}
}
}

运行结果

数组最大值:9,最小值:1

二、 均值(算术平均值)

1. 是什么

一组数值的总和除以该组数值的个数,反映数据的总体平均水平,结果通常为浮点型(避免整数除法丢失精度),核心是「先求和,再除个数」。

2. C# 代码实现

using System;

class MathAlgorithms
{
static void Main(string[] args)
{
// 测试正常数组
int[] normalNums = { 5, 2, 9, 1, 7, 4 };
double average = GetAverage(normalNums);
Console.WriteLine($"正常数组算术平均值:{average:F2}"); // F2 保留2位小数

// 测试空数组(验证无效场景处理)
int[] emptyNums = null;
double emptyAverage = GetAverage(emptyNums);
Console.WriteLine($"空数组返回的平均值:{emptyAverage:F2}");
}

static double GetAverage(int[] nums)
{
// 处理数组为 null 或空数组的情况(去掉 throw,改为提示+返回 0.0)
if (nums == null || nums.Length == 0)
{
Console.WriteLine("【提示】数组为空或无效,无法计算算术平均值,返回默认值 0.0");
return 0.0; // 返回 double 类型默认值,避免程序崩溃
}

// 原核心逻辑:求和 → 转为 double 计算平均值,保留精度
int sum = 0;
foreach (int num in nums)
{
sum += num;
}

return (double)sum / nums.Length;
}
}

运行结果

数组算术平均值:4.67

三、 公约数(最大公约数GCD)

1. 是什么

指两个或多个整数共有的约数中最大的那个(通常优先实现两个数的最大公约数),最常用高效的算法是「欧几里得算法(辗转相除法)」,核心逻辑:GCD(a, b) = GCD(b, a % b),直到余数为0,此时的非零数即为最大公约数。

2. C# 代码实现

求最大公约数(GCD):

一个名字、两种方法、两种时间复杂度

public static void Main()
{
// 求最大公约数
int result1 = GCD1(18,24);
int result2 = GCD2(18,24);

Console.WriteLine(result1);
Console.WriteLine(result1);
}
// 辗转相减法(时间复杂度:O(n))
static int GCD1(int a,int b)
{

// 先处理非正整数(最大公约数仅针对正整数)
a = Math.Abs(a);
b = Math.Abs(b);

while(a != b)
{
if(a > b) a -= b;
if(b > a) b -= a;
}
return a;
}
// 辗转相除法(时间复杂度:O(log n) )
static int GCD2(int a,int b)
{
// 健壮性处理:转为非负数(公约数不考虑正负)
a = Math.Abs(a);
b = Math.Abs(b);

// 辗转相除:直到余数为0
while (b != 0)
{
int remainder = a % b;
a = b;
b = remainder;
}

// 有问题
// while(b != 0)
// {
// if( a > b ) a %= b;
// if(b > a) b %= a;
// }

return a;
}

运行结果

24 和 18 的最大公约数:6

四、 素数(质数)

1. 是什么

大于1的自然数,除了1和它本身之外,无法被其他自然数整除(如2、3、5、7)。注意:1既不是素数也不是合数(除了1和它本身以外,还能被其他正整数整除的自然数(大于1),2是唯一的偶素数。优化技巧:判断时只需遍历到该数的平方根(√n),无需遍历到n-1,大幅提高效率。

2. C# 代码实现

using System;

class MathAlgorithms
{
static void Main(string[] args)
{
int num = 29;
bool isPrime = IsPrime(num);
Console.WriteLine($"{num} {(isPrime ? "是" : "不是")}素数");
}

static bool IsPrime(int num)
{
// 边界条件处理
if (num <= 1) return false; // 小于等于1不是素数
if (num == 2) return true; // 2是素数
if (num % 2 == 0) return false; // 大于2的偶数不是素数

// 优化:遍历到√num即可,步长为2(只判断奇数)
int sqrtNum = (int)Math.Sqrt(num);
for (int i = 3; i <= sqrtNum; i += 2)
{
if (num % i == 0)
{
return false; // 能被其他数整除,不是素数
}
}

return true;
}
}

运行结果

29 是素数

五、 累加

1. 是什么

将一组数值依次相加得到总和(通用累加),也可特指「1到n的连续整数累加」(专项累加),核心是「初始化累加器,遍历叠加」。

2. C# 代码实现

using System;

class MathAlgorithms
{
static void Main(string[] args)
{
// 场景1:数组元素通用累加
int[] nums = { 1, 2, 3, 4, 5 };
int arraySum = AccumulateArray(nums);
Console.WriteLine($"数组累加总和:{arraySum}");

// 场景2:1到n的连续累加
int n = 100;
int continuousSum = AccumulateContinuous(n);
Console.WriteLine($"1到{n}累加总和:{continuousSum}");
}

// 数组元素通用累加
static int AccumulateArray(int[] nums)
{
if (nums == null) return 0;
int sum = 0;
foreach (int num in nums)
{
sum += num;
}
return sum;
}

static int AccumulateContinuous(int n)
{
if (n < 1) return 0;
int sum = 0;
for (int i = 1; i <= n; i++)
{
sum += i;
}
return sum;
}
}

运行结果

数组累加总和:15
1到100累加总和:5050

六、 累乘

1. 是什么

将一组数值依次相乘得到总乘积(通用累乘),也可特指「1到n的连续整数累乘」(专项累乘,区别于阶乘:阶乘是n!,累乘范围更灵活),注意乘积可能溢出,优先使用long类型存储结果。

2. C# 代码实现

using System;

class MathAlgorithms
{
static void Main(string[] args)
{
// 场景1:数组元素通用累乘
int[] nums = { 2, 3, 4, 5 };
long arrayProduct = MultiplyArray(nums);
Console.WriteLine($"数组累乘总乘积:{arrayProduct}");

// 场景2:1到n的连续累乘
int n = 6;
long continuousProduct = MultiplyContinuous(n);
Console.WriteLine($"1到{n}累乘总乘积:{continuousProduct}");
}

// 数组元素通用累乘
static long MultiplyArray(int[] nums)
{
if (nums == null || nums.Length == 0) return 0;
long product = 1; // 累乘初始值为1(累加初始值为0)
foreach (int num in nums)
{
product *= num;
}
return product;
}

// 1到n的连续整数累乘
static long MultiplyContinuous(int n)
{
if (n < 1) return 0;
long product = 1;
for (int i = 1; i <= n; i++)
{
product *= i;
}
return product;
}
}

运行结果

数组累乘总乘积:120
1到6累乘总乘积:720

七、 阶乘

1. 是什么

对于非负整数nn的阶乘(记作n!)是1到n所有正整数的累乘,规定0! = 11! = 1,核心公式:n! = n × (n-1)!(递归思想),n ≥ 2

2. C# 代码实现

using System;

class MathAlgorithms
{
static void Main(string[] args)
{
int n = 5;
// 非递归版(推荐,避免大数栈溢出)
long factorialIter = FactorialIterative(n);
Console.WriteLine($"{n}!(非递归)= {factorialIter}");

// 递归版(简洁,适合理解递归逻辑)
long factorialRecur = FactorialRecursive(n);
Console.WriteLine($"{n}!(递归)= {factorialRecur}");
}

// 阶乘(非递归版)
static long FactorialIterative(int n)
{
if (n < 0) throw new ArgumentException("阶乘仅支持非负整数");
if (n == 0 || n == 1) return 1;

long result = 1;
for (int i = 2; i <= n; i++)
{
result *= i;
}
return result;
}

// 阶乘(递归版)
static long FactorialRecursive(int n)
{
if (n < 0) throw new ArgumentException("阶乘仅支持非负整数");
// 递归终止条件
return n == 0 || n == 1 ? 1 : n * FactorialRecursive(n - 1);
}
}

运行结果

5!(非递归)= 120
5!(递归)= 120

八、 回文数

1. 是什么

一个整数正读和反读完全相同(如121、1331、5),负数因包含负号(-121反读为121-),不是回文数。实现思路有两种:

  • ① 转为字符串反转比对;
  • ② 纯数字运算反转,避免字符串操作。

2. C# 代码实现

using System;

class MathAlgorithms
{
static void Main(string[] args)
{
int num1 = 12321, num2 = 12345;
// 方法1:字符串反转法(简洁易懂)
Console.WriteLine($"{num1}(字符串法){(IsPalindromeString(num1) ? "是" : "不是")}回文数");
Console.WriteLine($"{num2}(字符串法){(IsPalindromeString(num2) ? "是" : "不是")}回文数");

// 方法2:纯数字运算法(高效,无字符串转换开销)
Console.WriteLine($"{num1}(数字法){(IsPalindromeNumber(num1) ? "是" : "不是")}回文数");
Console.WriteLine($"{num2}(数字法){(IsPalindromeNumber(num2) ? "是" : "不是")}回文数");
}

// 判断回文数(字符串反转法)
static bool IsPalindromeString(int num)
{
if (num < 0) return false; // 负数不是回文数
string str = num.ToString();
char[] charArr = str.ToCharArray();
Array.Reverse(charArr);
string reversedStr = new string(charArr);
return str == reversedStr;
}

// 判断回文数(纯数字运算法)
static bool IsPalindromeNumber(int num)
{
if (num < 0) return false;
int originalNum = num;
long reversedNum = 0; // 避免反转后溢出

// 反转数字
while (num > 0)
{
int remainder = num % 10; // 取最后一位
reversedNum = reversedNum * 10 + remainder;
num /= 10; // 移除最后一位
}

return originalNum == reversedNum;
}
}

运行结果

12321(字符串法)是回文数
12345(字符串法)不是回文数
12321(数字法)是回文数
12345(数字法)不是回文数

九、 斐波那契数列

1. 是什么

又称黄金分割数列,有两种常见约定:

  • ① 前两项为0、1,从第三项开始,每一项等于前两项之和(F(0)=0, F(1)=1, F(n)=F(n-1)+F(n-2));
  • ② 前两项为1、1F(1)=1, F(2)=1)。这里采用第一种约定,实现思路:递归(简洁但低效)、非递归(迭代,高效推荐)。

2. C# 代码实现

using System;
using System.Collections.Generic;

class MathAlgorithms
{
static void Main(string[] args)
{
int n = 10;
// 场景1:获取第n项斐波那契数(非递归版)
long fibN = GetFibonacciNth(n);
Console.WriteLine($"斐波那契数列第{n}项:{fibN}");

// 场景2:获取前n项斐波那契数列(非递归版)
List<long> fibList = GetFibonacciList(n);
Console.WriteLine($"前{n}项斐波那契数列:{string.Join(", ", fibList)}");
}

// 获取第n项斐波那契数(非递归版,高效)
static long GetFibonacciNth(int n)
{
if (n < 0) throw new ArgumentException("n必须为非负整数");
if (n == 0) return 0;
if (n == 1) return 1;

long a = 0, b = 1;
long result = 0;
for (int i = 2; i <= n; i++)
{
result = a + b;
a = b;
b = result;
}
return result;
}

// 获取前n项斐波那契数列(非递归版)
static List<long> GetFibonacciList(int n)
{
if (n <= 0) throw new ArgumentException("n必须为正整数");
List<long> fibList = new List<long>();

if (n >= 1) fibList.Add(0);
if (n >= 2) fibList.Add(1);

long a = 0, b = 1;
for (int i = 2; i < n; i++)
{
long c = a + b;
fibList.Add(c);
a = b;
b = c;
}

return fibList;
}

// 可选:递归版(低效,n较大时栈溢出,仅用于理解逻辑)
static long GetFibonacciRecursive(int n)
{
if (n < 0) throw new ArgumentException("n必须为非负整数");
return n == 0 ? 0 : (n == 1 ? 1 : GetFibonacciRecursive(n - 1) + GetFibonacciRecursive(n - 2));
}
}

运行结果

斐波那契数列第10项:55
前10项斐波那契数列:0, 1, 1, 2, 3, 5, 8, 13, 21, 34

总结

  1. 基础统计类(最值、均值):核心是遍历数据,累加/比对即可实现,注意均值的浮点型转换避免精度丢失。
  2. 数论类(公约数、素数):公约数用欧几里得算法高效求解,素数判断可优化到遍历平方根,提升效率。
  3. 累积运算类(累加、累乘、阶乘):累加初始值为0,累乘/阶乘初始值为1,阶乘支持递归/非递归,非递归更稳定。
  4. 特殊判断类(回文数):有字符串和纯数字两种实现,纯数字法无额外开销,更高效。
  5. 数列类(斐波那契):递归简洁但低效,非递归迭代法是工业级推荐,避免栈溢出和重复计算。