机试备考——刷题攻略

  为了准备保研的机试,在学习完常见算法后,开始了刷题!看了一些大佬的心得分享,总结了一下。  在刷LeetCode的时候还要有一定的策略,比如按标签刷题,分为数组、字符串、链表、双指针、BFS/DFS,二叉树、二分法、分治法、回溯法、数学、栈、堆、队列等按类型集中刷,刷完后做笔记。  按标签刷完后,再补top100中没刷到的题。  接下来我总结了一下我依照上述策略刷题的题目和答案。...
摘要由CSDN通过智能技术生成

  为了准备保研的机试,在学习完常见算法后,开始了刷题!看了一些大佬的心得分享,总结了一下。

  题目类型分为:

  数组、字符串、高精度计算、排序、递推、递归、搜索与回溯、贪心算法、分治算法、动态规划、栈、队列、树、图论算法

  按类型刷,刷完后做笔记。

  因为不喜欢LeetCode那种答案要封装起来的写法,我选择了在N诺/洛谷上刷题。

  接下来我总结了一下我刷题的重点题目和答案。

N诺

分类和提交的感觉都挺好的,就是题目太少了,所以后来主刷洛谷

简单模拟(答案链接)

01序列

对于长度为6位的一个01串,每一位都可能是0或1,一共有64种可能。它的前几个是:
000000
000001
000010
000011
000100
请按从小到大的顺序输出这64种01串。

思路: 将0~63分别进行十进制转二进制,然后用“%06d”格式输出。(进制转换

随机数

从1—20之间随机抽取5个数,输出抽取出来的5个数之和与剩余未被抽取的15个数之和的总和。

思路:题目很蠢,就是1+····+20求和,只是之前没有遇到过随机数,所以记录一下。

产生一定范围随机数的通用表示公式

  1. 要取得[a,b)的随机整数,使用(rand() % (b-a))+ a;
  2. 要取得[a,b]的随机整数,使用(rand() %(b-a+1))+ a;
  3. 要取得(a,b]的随机整数,使用(rand() % (b-a))+ a + 1; 通用公式:a +rand() % n;其中的a是起始值,n是整数的范围。
  4. 要取得a到b之间的随机整数,另一种表示:a + (int)b * rand()/ (RAND_MAX + 1)。
  5. 要取得0~1之间的浮点数,可以使用rand() / double(RAND_MAX)。
	a[i]  = rand()%(20-1+1) + 1;//产生1-20之间的随机数

日期

今天是2012年4月12日星期四,编写程序,输入今天(2012年)开始到12月31日之间的任意日期,输出那一天是星期几。例如输入“5(回车)20(回车)”(5月20日),输出应为“Sunday”。

更多有关日期的问题见

计算输入日期和20120412之间的天数
之后天数+4(星期四)
对7取模得到的余数就是星期几

单链表

设节点定义如下

struct Node {
   
    int Element; // 节点中的元素为整数类型
    struct Node * Next; // 指向下一个节点
};

从键盘输入5个整数,将这些整数插入到一个链表中,并按从小到大次序排列,最后输出这些整数。

练习单链表的建立和排序!

链表合并

给定两个元素有序(从小到大)的链表,要求将两个链表合并成一个有序(从小到大)链表。

思路:类似合并排序,只不过将数组变为链表的形式。

while(p1 && p2) //判断两个链表是否有一个合并结束

删除字符串

给你一个字符串S,要求你将字符串中出现的所有"gzu"(不区分大小写)子串删除,输出删除之后的S。
就是说出现“Gzu”、“GZU”、“GZu”、"gzU"都可以删除。

思路:STL的string容器中提供transform函数(大小写转换)、find函数(找到子串位置)和erase函数(删除部分区间子串)。

阶乘求和

求Sn=1!+2!+3!+4!+5!+…+n!之值,其中n是一个数字。

思路:直接使用递归会导致超时。使用

for (int i = 1; i <= n; i++) {
   
		num *= i;
		ans += num;
}

来降低复杂度

括号的匹配

在算术表达式中,除了加、减、乘、除等运算外,往往还有括号。包括有大括号{},中括号[],小括号(),尖括号<>等。 对于每一对括号,必须先左边括号,然后右边括号;如果有多个括号,则每种类型的左括号和右括号的个数必须相等;对于多重括号的情形,按运算规则,从外到内的括号嵌套顺序为:大括号->中括号->小括号->尖括号。例如,{[()]},{()},{ {}}为一个合法的表达式,而([{}]),{([])},[{<>}]都是非法的。

注意:同级嵌套是允许的(如:{ {}}),使用栈来答题
遍历字符串,遇到左括号时,先和栈顶元素判断是否符合括号优先级,不符合直接GG。否则入栈。
遇到右括号时,看和栈顶的括号是否相匹配,是的话弹出栈顶元素,不是的话直接GG。
最后再判断一下栈内元素是否全部弹出,栈内还有括号未匹配,直接GG,否则合法。
栈在使用pop()时需要先判断empty()

注意:使用goto来跳出多重循环,此时continue只能跳出一层

基础算法

成绩排序

题目:输入任意(用户,成绩)序列,可以获得成绩从高到低或从低到高的排列,相同成绩都按先录入排列在前的规则处理。

当遇到相同数据按输入顺序排列的时候要使用稳定排序stable_sort()【不能使用sort()】

玛雅人的秘密

玛雅人有一种密码,如果字符串中出现连续的2012四个数字就能解开密码。给一个长度为N的字符串,(2=<N<=13)该字符串中只含有0,1,2三种数字,问这个字符串要移位几次才能解开密码,每次只能移动相邻的两个数字。例如02120经过一次移位,可以得到20120,01220,02210,02102,其中20120符合要求,因此输出为1(输出交换次数).如果无论移位多少次都解不开密码,输出-1。

参考https://www.jianshu.com/p/fa96e0c90e0e的思路。
使用bfs层次遍历树
在这里插入图片描述

最简真分数

给出n个正整数,任取两个数分别作为分子和分母组成最简真分数,编程求共有几个这样的组合。

思路:
最简真分数 = 分子和分母的最大公因数为1

逆序对

猫猫 TOM 和小老鼠 JERRY 最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏,现在他们喜欢玩统计。
最近,TOM 老猫查阅到一个人类称之为“逆序对”的东西,这东西是这样定义的:对于给定的一段正整数序列,逆序对就是序列中 ai​>aj​ 且 i<j 的有序对。知道这概念后,他们就比赛谁先算出给定的一段正整数序列中逆序对的数目。
输入:
第一行,一个数 n,表示序列中有 n个数(n < 10^5)。
第二行 n 个数,表示给定的序列。序列中每个数字不超过 10^9。


当输入数字很大的时候,直接使用两层循环会导致超时,只能过一半的数据。
使用分治+归并排序
读入的数每次划分后合并时左右子区间都是从小到大排好序的,我们只需要统计左边区间每一个数分别会与右边区间产生多少逆序对即可。
(因为在左边的数无论怎么排序,排序好后还是都是在 右边的数的前面。所以我们可以查下左边与右边能产生多少对逆序对就好了。
又因为左边的是按小到大排序的
所以只要左边第一个 > 右边第一个,那么表示左边所有数都大于右边第一个
,左边多少数就有多少对逆序。然后让右边的指向第二个。继续重复(ans += mid -i +1;)
如果左边第一个小于右边第一个,那就让左边指向第二个,然后继续。

放在合并排序代码中间计算逆序对个数

while(i<=R1 && j<=R2){
   
		if(a[i]<=a[j]){
   
			b[index++] = a[i++];
		}else{
   
			b[index++] = a[j++];
			ans 
  • 0
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值