基本算术
求平均值
给定一个long
型数组,求数组的平均值。
- 首先为防止两个
long
相加越界,可以采用先除再加的方法,保证了总和不会越界
\[ \frac{\sum_{i=0}^{n-1} \operatorname{arr}[i]}{n}=\sum_{i=0}^{n-1} \frac{\operatorname{arr}[i]}{n} \]
不能采用浮点数的方案,因为浮点数的精度损失是不可控的,所以应该选择使用余数来收集小数部分 \[ \sum_{i=0}^{n-1} \frac{\operatorname{arr}[i]}{n}=\sum_{i=0}^{n-1} \operatorname{long}\left(\frac{\operatorname{arr}[i]}{n}\right)+\frac{\sum_{i=0}^{n-1} \operatorname{arr}[i] \%(n)}{n} \]
但是这还有一个问题,余数部分的相加仍有越界的风险,在实际计算的过程中,应该累加到大于等于
n
或者小于等于-n
之后,就累加一个1或者-1给最终的结果1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21long get_avg(long* arr, long length){
long MLONG_MAX = length;
long MLONG_MIN = -MLONG_MAX;
long ans=0;
long mod=0;
long x;
for(long i=0;i<length;++i){
ans+=arr[i]/length;
x=arr[i]%length;
if(x+mod>=MLONG_MAX){
ans++;
mod=mod-MLONG_MAX+x;
}else if(x+mod<=MLONG_MIN){
ans--;
mod=x-MLONG_MIN+mod;
}else{
mod+=x;
}
}
return ans+mod/length;
}
备注:C++中的负数取余计算逻辑
1 | int main(void){ |
大数相乘
大数相乘,若结果过大应该对1e9+7
取模。将乘法分解 \[
\begin{array}{l}(a * b) \equiv m \\ =\left(\sum b * a_{i}\right) \equiv m, \ \ a=\sum a_{0}+a_{1}+\cdots+a_{r} \\ =\sum (b * a_{i}) \equiv m\end{array}
\] 我们可以将a拆解成如下部分 \[
a=x_{0} * 2^{0}+x_{1} * 2^{1}+x_{n} * 2^{n}, x_{i} \in\{0,1\}
\\ x_{i}=\frac{a}{2^{i}} \% 2
\] 程序实现
1 | long long m(long long a, long long b){ // 大数相乘 |
南航机试常用方法与技巧
日期的处理
判断某个年份是不是闰年
1 | bool ISYEAP(int x){ |
计算两个日期之间的差值的思想:记录所有天数到元年的天数差
二分查找
1 | // 在一个数组中查找某个数 |
属性数值
最大公约数 & 最小公倍数
最大公约数:两个整数共有约数最大的一个
最小公倍数:两个整数共有倍数最大的一个
1 | int gcd(int x, int y){ |
大整数求余
定义a
,b
和m
,若满足(a-b)/m为整数,那么就称a
和b
对模m
同余,计作 \[
\mathrm{a} \equiv \mathrm{b}(\mathrm{mod} \ \mathrm{m})
\] 对模m同余是整数的一个等价关系。
1 | // 基于等价关系,对大数求余数 |
素数
只能被1和它自身整除的数
对于n,对2到sqrt(n)
的整数分别测试是否可被整除即可。
哈夫曼树
利用小根堆,每次取权重最小的两个节点,合并成一个新的节点,该节点的权重为两个叶子结点的权重只和,直到小根堆中只有一个节点。(先合并的节点的深度更可能会比较的深)
并查集
1 | const int N=10008; |
Github
排序算法
排序算法 | 平均时间复杂度 | 最差时间复杂度 | 空间复杂度 | 数据对象稳定性 | |
---|---|---|---|---|---|
冒泡排序 | O(n2) | O(n2) | O(1) | 稳定 | |
选择排序 | O(n2) | O(n2) | O(1) | 数组不稳定、链表稳定 | |
插入排序 | O(n2) | O(n2) | O(1) | 稳定 | |
快速排序 | O(n*log2n) | O(n2) | O(log2n) | 不稳定 | |
堆排序 | O(n*log2n) | O(n*log2n) | O(1) | 不稳定 | |
归并排序 | O(n*log2n) | O(n*log2n) | O(n) | 稳定 | |
希尔排序 | O(n*log2n) | O(n2) | O(1) | 不稳定 | |
计数排序 | O(n+m) | O(n+m) | O(n+m) | 稳定 | |
桶排序 | O(n) | O(n) | O(m) | 稳定 | |
基数排序 | O(k*n) | O(n2) | 稳定 |
不稳定的排序算法有
选择排序、快速排序、堆排序、希尔排序
选择排序不稳定的例子
- 2 5 9 3 4 [7] 1...
在第一次选择的时候,最小的元素是1,被交换到了(7)的位置上,然后(7)和[7]之间的相对位置就发生了变化。
网上资源
资源来源
- 南航机试常用方法与技巧 2018.03 金航