这里讲解大致思路,,观看本讲解你必须有耐心,没有耐心你学不会算法。
一.前缀和
具体示例:
arr = [1, 2, 3, 4, 5];
prefix_sum[]; //前缀和数组
prefix_sum[i] = arr[0] + arr[1] + ... + arr[i];
prefix_sum[0] = 0
prefix_sum[1] = 1 (1)
prefix_sum[2] = 3 (1 + 2)
prefix_sum[3] = 6 (1 + 2 + 3)
prefix_sum[4] = 10 (1 + 2 + 3 + 4)
prefix_sum[5] = 15 (1 + 2 + 3 + 4 + 5);
//最终,前缀和数组为 [0, 1, 3, 6, 10, 15]。
适用于:
1.快速计算数组中区间的和。
2.一些更复杂的算法,如二维前缀和,用于计算矩阵的区域和
将计算的复杂度由 O(n) 降到 O(1) ,非常适合于频繁查询区间和的题型。
二.高精度
1.高精度加法
这里我只记录大致的思想。高精度,数字的长度可以成百上千,因此计算采用字符串类型,
给出两个超长数字字符串,num1,num2,已存储两个长整形数字。
首先,比较两个字符串的 length ,如果 num1.length <num2.length ,交换;
然后定义进位 int carry=0;
然后就是循环,从个位开始相加,这里示例代码,如果没有将字符串逆置,就需要从字符串的最后开始相加;
for(int i=0;i<num1.length();i++){
int n1=num1.charAt(num1.length()-1-i)-'0';
//这里num1.length()-1-i是从个位开始相加,
int n2=(i<num2.length())?num2.charAt(num2.length()-1-i)-'0':0;
int sum=n1+n2+carry;
result.append(sum%10);//这里我使用的是Java,将每次相加的数加到字符串中,
carry=sum/10;
}
最后,如果 carry>0 还需要将进位添加到最后;
最后提交,需要将结果逆置,因为相加是从个位相加(个 十 百 千,,),再向后逐个加和,因此结果需要逆置。
2.高精度减法
这里相较于加法类似,前面依旧是比较字符串的长度,较长的放前面,不过,区别在于,如果置换的话需要添加负号。
// 比较两个数的大小
int comparison = compare(num1, num2);
// 如果 num1 < num2,交换它们并在结果前添加负号
boolean isNegative = false;
if (comparison < 0) {
String temp = num1;
num1 = num2;
num2 = temp;
isNegative = true; // 结果为负
} else if (comparison == 0) {
return "0"; // 两个数相等,结果为0
}
然后就开始相减字符串,
StringBuilder result = new StringBuilder();
int carry = 0; // 借位
int n1 = num1.length();
int n2 = num2.length();
// 从后往前进行减法
for (int i = 0; i < n1; i++) {
int digit1 = num1.charAt(n1 - 1 - i) - '0'; // num1 当前位
int digit2 = (i < n2) ? num2.charAt(n2 - 1 - i) - '0' : 0; // num2 当前位
digit1 -= carry; // 减去借位
if (digit1 < digit2) {
digit1 += 10; // 借位
carry = 1;
} else {
carry = 0;
}
result.append(digit1 - digit2);
}
这样得到的结果是反着的仍需要用一个倒置函数反过来,如果在高位是 0 的话还需去除 0 ,其次,如果是负数,千万别忘负号。
3.Java标准库函数:BigInteger BigDecimal
BigInteger
用于处理大整数。它可以进行基本的数学运算,如加法、减法、乘法和除法。
import java.math.BigInteger;
public class BigIntegerExample {
public static void main(String[] args) {
BigInteger num1 = new BigInteger("123456789123456789123456789");
BigInteger num2 = new BigInteger("987654321987654321987654321");
// 加法
BigInteger sum = num1.add(num2);
//减法
BigInteger difference = num1.subtract(num2);
// 乘法
BigInteger product = num1.multiply(num2);
// 除法
BigInteger quotient = num2.divide(num1);
System.out.println("和: " + sum);
System.out.println("差:" + difference);
System.out.println("积: " + product);
System.out.println("商: " + quotient);
}
}
BigDecimal
用于高精度的小数运算,避免了浮点数运算的精度问题。它允许指定精度和舍入模式,适用于金融应用。
import java.math.BigDecimal;
import java.math.RoundingMode;
public class BigDecimalExample {
public static void main(String[] args) {
BigDecimal num1 = new BigDecimal("12345.6789");
BigDecimal num2 = new BigDecimal("987.654321");
// 加法
BigDecimal sum = num1.add(num2);
// 减法
BigDecimal difference = num1.subtract(num2);
// 乘法
BigDecimal product = num1.multiply(num2);
// 除法
BigDecimal quotient = num1.divide(num2, 2, RoundingMode.HALF_UP); // 保留两位小数
}
}
4.valueOf
函数
BigInteger
中的 valueOf
函数的作用是将基本数据类型(如 int
、long
或 String
)转换为一个 BigInteger
对象。这个方法提供了一种方便的方式来创建 BigInteger
实例。
三.二分查找
二分排序是排序算法中的较好(就是效率高)的一种。就像孔子说的那个,一尺之锤,日取其半,但这里可不是永世不竭。这里主要告诉你是对半分割的思想。
先说前提,数组必须是有序的,就必须先排序(升序,降序都行,升序较多),这也是这种查找的美中不足。(升序:从小到大)
基本步骤:(升序)
- 初始化边界:定义查找范围的两个边界,通常用
left
和right
表示。 - 计算中间索引:计算中间索引
mid = left + (right - left) / 2
。 - 比较中间值:
- 如果中间值等于目标值,查找成功,返回索引。
- 如果中间值大于目标值,则在左半部分继续查找(更新
right = mid - 1
)。 - 如果中间值小于目标值,则在右半部分继续查找(更新
left = mid + 1
)。
- 重复步骤 2 和 3,直到找到目标值或者查找范围为空(即
left > right
)。
四.差分
。。。还不会,,其实自我感觉就开始将数学向计算机转移了,所以高数别挂,
大致看看这个先,目前也用的少,
1. 差分方法概述
五,模拟
“ 模拟题 ” 通常指的是一种需要通过模拟某个过程或状态来解决的问题。这类题目往往要求按照题目的描述逐步执行特定的操作,最终得到结果。
六,贪心
贪心算法(Greedy Algorithm)是一种解决问题的方法,旨在通过在每一步选择中都做出当前最优的选择,从而期望能够达到全局最优解。贪心算法的基本思想是:在每个阶段都选择局部最优解,最终构造出全局最优解。
特点
- 局部最优选择:每一步都选择当前状态下最优的解决方案,而不考虑后续可能的影响。
- 无回溯:一旦做出选择,就不会再回头进行调整或重新考虑。
- 适用性:并不是所有问题都适合用贪心算法解决,只有在满足“贪心选择性质”和“最优子结构”的问题中,贪心算法才会得出最优解。
贪心算法的基本步骤
- 定义问题:明确要解决的问题和目标。
- 选择标准:确定在每一步中选择的标准。
- 迭代选择:从可行选择中进行选择,直到满足结束条件。