整理资料发现了当初准备保研机试记录的算法笔记,大概内容是把一本书的所有算法做完了。当时用的还是C++,现在不用了,不分享出来的话可能这个文件永远都不会被打开了。
机试算法笔记笔记
C++基础
-
字符常量是单个使用单引号标记的字符;字符串常量则是由双引号标记的字符集。字符串常量可以作为初值赋给字符数组,并使用%s的格式输出。(不能把字符串常量赋值给字符变量)
-
**条件判断是 == **
-
字符所表示的数字的值 = 该字符与字符‘0’的ASCII的值的差( a - ‘0’) 字符一定是单引号!!!
-
长整型为 long long,输入时为scanf("%lld",&x)
-
do while可以先执行一次
-
c++如何输入含空格的字符:https://blog.csdn.net/qq_36553031/article/details/82746459
-
memset()只能初始化0 -1
编程技巧
- sqrt()、strlen() 是比较耗时的函数,尽量只执行一次
算法入门
排序
用STL模版
```
#include<algorithm> //排序算法在这里面
bool cmp (int x, int y){
return x < y;
}//自定排序规则
int main()
{
int numbers[100];
sort(numbers,numbers+100,cmp);
return 0;
}
```
- cmp是排序规则,可以重写它来达到各种排序目的
- 字符转ASCII码:(int)‘a’
- 字符串结束符:’\0’
- 输出中的空格也不能少
- 重载运算符要写在STRUCT的定义体中
cin.getline(char[],n)
:getline()函数用于读取整行,它使用通过回车键键入的换行符来确定输入结尾。直到读满n-1个,或者遇到指定的结束符为止。
日期类问题
大概结构:
(在main()外)
- 定义一个日期类(struct)包括:年月日、下一天函数
- 声明一个三维数组[年][月][日]用来存当天距0/1/1多少天
- 定义一个绝对值求法
(在main()里)
- 算出五千多年里的每一天距0/1/1的天数
- 输入两个日期,距0/1/1的天数相减
- 定义宏 :#define A(x) x,可以用来计算闰年
scanf("%4d%2d%2d",&y2,&m2,&d2)
:读一个数的前4位、2位strcmp(str1,str2)
:str1=str2,返回0、str1>str2,返回一个正整数、str1<str2,返回一个负整数。- 判断是否输入结束! :if(!(cin>>n)) 既能判断又能输入
Hash思想
所有的可能性是可以穷举的。
排版题
查找
- 二分查找:先关键字排序,保证查找空间单调有序.
int binarySearch(int A[], int left, int right, x)
{
int mid;//mid为left和right的中点
while(left <= right) //存在区间
{
mid = (left + right)/2;
if(A[mid]==x)
return mid;
if(x < A[mid])
{
right = mid-1;
}
if(A[mid] > x)
{
left = x+1;
}
}
return -1;//查找失败, 返回-1
}
贪心算法
滑动窗口
无重复字符的最长字串
用unordered_set< char> lookup来存字符
for(int i=0;i<s.length();i++)
{
while(lookup.find(s[i])!=lookup.end())
{
lookup.erase(s[left]);
left++
}
maxstr = max(maxstr , i-left+1);
lookup.insert(s[i]);
}
数据结构
栈
- #include<stack>:并声明使用标准命名空间。
- stack<int> S; :定义一个保存元素类型为 int 的堆栈 S
- top():返回一个栈顶元素的引用,类型为 T&。如果栈为空,返回值未定义。
- push(obj):添加新的栈顶元素
- pop():弹出栈顶元素。
- size():返回栈中元素的个数。
- empty():在栈中没有元素的情况下返回 true。
栈-中缀表达式转后缀表达式
中缀表达式a + b*c + (d * e + f) * g,其转换成后缀表达式则为a b c * + d e * f + g * +。
- 如果遇到操作数,我们就将操作数直接输出
- 如果遇到左括号,放入到stack中
- 如果遇到右括号,则将stack中左括号之前的运算符全输出,并将左括号pop
- 如果遇到运算符,则将其与stack顶运算符相比较:若优先级高于stack顶运算符,则直接存入stack;否则,则弹出stack顶运算符直至当前优先级高于stack顶或为空
- 扫描结束,stack还不为空,全弹出。
注意事项:先判断栈是否为空,否则.top()报错
哈夫曼树
- priority_queue<int, vector<int>, greater<int> > :小顶堆实现
- 节点合并放回小顶堆前先累加一次,这样可以实现路径✖️权值
二叉树
-
前、中、后序遍历: print 根;递归左子树;递归右子树。 三者组合为各种遍历。
-
**中序、前/后序得一棵树:**画个图
-
二叉排序树的生成[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hEzrJGFK-1645613153588)(C:\Users\I354881\AppData\Roaming\Typora\typora-user-images\1567654047305.png)]
Map
- map<typename1 , typename2>
- 给map赋新值时:
int cnt=1;
for(int i=0; i<len ;i++)
{
if(map.find(str[i])==map.end())
{
map[str[i]] = cnt++;
}
else
{
//map[str[i]]已经存在
}
}
-
遍历map:
for(map<type1 , type2>::iterator it=mp.begin(); it!=mp.end(); it++) { it->first; it->second; }
数论
%运算
- ( a ∗ b ) % c = ( a % c ∗ b % c ) % c ( a * b) \% c = (a\%c * b\%c)\%c (a∗b)%c=(a%c∗b%c)%c ; ( a + b ) % c = ( a % c + b % c ) % c ( a + b) \% c = (a\%c + b\%c)\%c (a+b)%c=(a%c+b%c)%c
- **%**运算可以取到一个数的每一位,%10可以取最后一位,%100可以取后两位;或者%10,然后➗10,再%10,取到每一位。
最大公约数——欧几里得算法
- a、b全为零,最大公约数不存在;
- a、b其中之一为零,则最大公约数为a、b中非零的那一个;
- 若a、b全不为零,新a = b,新b = a % b;递归
最小公倍数
a、b两数的最小公倍数为两数的乘积除以它们的最大公约数。
约数个数
i i i从1开始遍历到 n \sqrt{n} n -1,若 ( n % i = = 0 ) (n \% i ==0) (n%i==0) 计数器加2;遍历结束后检查n是不是平方数,是的话计数器再加1.
素数筛法
除了1和其本身以外,没有其他因数。测试 1 1 1 ~ n \sqrt{n} n 之间的数能否被n整除就可以了,时间复杂度降到了 O ( n ) O(\sqrt{n}) O(n)
- 从2开始遍历2到n的所有整数,若当前整数没有因为它是某个小于其的素数的倍数而被标记成非素数,则判定其为素数,并标记它所有的倍数为非素数,然后继续遍历下个数。注:j并不用从 2 ∗ i 2*i 2∗i开始遍历,而是直接从 i ∗ i i*i i∗i开始遍历
分解素因数
求 N < 1 0 9 N < 10^9 N<109质因数,先求出 2 ∼ 1 0 5 2 \sim 10^5 2∼105 素因数prime[],然后用 N N N遍历prime[size],如可整除,$N/=prime[size] $ 。结束时若 N ! =