2020-C++高级程序设计-作业总结
1. 第一次作业总结
1.1. 最大的罗马数字
- 需要进行临近的两个数字的比较
- 先前看或者先后看一个都是可以的
1.2. X的Y次方
- 如何判断越界了
- 使用一个更大的数据类型可以处理
- 使用MAX_INT/x < now ?如果满足则会溢出
- 如果溢出的话会直接截取其低32位:我们可以先做,然后再逆运算看能不能回去(如果不能,则为已经溢出了)
1 |
|
1.3. 生成字符集的子集
- 找到包含对应的字母的所有子集
1.3.1. 递归方法(获取所有子集)
1 |
|
1.3.2. 排序
- cmp+sort
1 |
|
1.3.3. 位操作
- 例如{a,b,c}的子集,{a,b}可以是表示为110
- 长度为n的集合,就遍历长度为n的二进制数字来遍历
1 |
|
1.4. 秘钥字符串格式化
- 思路:倒排序
1.5. 素数之和
- 逐步优化
- 第一步优化:小于这个数的所有的数不可以被整除
- 第二步优化:只需要处理到<= sqrt(这个数)的情况
- 第三步优化:任何一个质数都是6x + 1或者 6x - 1//增加过滤条件
1.6. 计算二进制中1的个数
- 方法一:直接用位运算可以
- 但是最好要确定遍历次数,而不仅仅是0,因为-1等负数会出现问题
- 方法二:使用n & (n-1):统计n变为0有多少次操作
- 如果输入-1呢?是正确的
1 |
|
1.7. 字符统计
- 大写变小写,小写变大写: ch ^= 32
- 全部变小写: ch |= 32
- 全部变大写: ch &= 32(不可用)
1.8. 三角形种类判断
- 判断5中三角形
- 判断是否构成三角形:
bool isValid = (y2-y1)*(x3-x1) != (x2-x1)*(y3-y1)
:二维空间中只可能相同(斜率同)
1.9. 一年中的第几天
- 使用表驱动等等
- 进行微调
1.10. 笨阶乘
1.10.1. 常规法
- 直接循环进行计算就行
1 |
|
1.10.2. 找规律
1 |
|
2. 第二次作业
2.1. 第一题:四数之和
- 给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。
2.1.1. 解法一:简单的多重循环 + 结果排序
- 计算的时间复杂度过高
2.1.2. 优化启动!
2.1.3. 两数之和启发
- 如果数组有序就不用多重循环了
2.1.4. 三数之和
2.1.5. 结论
- 去重,如果相邻的数相同,需要跳过
- 如果最小的数已经比target大 那么就没有答案
2.2. 第二题:删除重复数字
- 给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数。
- 你需要原地删除重复出现的元素,使得每个元素只出现一次不要使用额外的数组空间,必须修改原输入数组并在使用O(1)额外空间的条件下完成。
2.2.1. 判断重复数字的一般思路
- 排序
- Hash结构 使用额外空间
- 类似抽屉原理:二分
2.2.2. 重复后修改
2.2.3. 抽屉原因:针对只有一个重复数字
1 |
|
2.3. 第三题:字符串压缩
- 给定一个字符串,按照重复进行压缩,如果比原来长不压缩
2.3.1. 代码实现
2.4. 第四题:矩阵旋转
- 将矩阵进行旋转
- 思路就是,将矩阵旋转90度,其他情况都可以认为是90度的变形。
2.4.1. 暴力法
- 构造一个新的矩阵,然后将旋转后对应位置的数据放在当前位置,比如示例中的7应该放在1的位置。matrix_new[col][n-row-1] = matrix[i][j]
2.4.2. 原地旋转
- 原地旋转:根据上述规律对空间复杂度进行优化
- 考虑一个元素的联动性,比如上述示例中的1,3,7,9为一个联动,所以在一次循环中,我们做的事情就是将联动的值进行旋转。这样只需要O(1)的空间复杂度
2.5. 第五题:柱状图的最大矩形面积
- 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子中矩形的最大面积。
2.5.1. 题目思路
- 对每根柱子,都找到高为柱子高度的面积最大的长方形
- 比较所有长方形的大小,找出最大的长方形
- 怎么找到高为柱子高度的最大的长方形?
- 找到柱子左右两边第一个高度比柱子低的柱子,这两根柱子之间的宽度就是面积最大的长方形的宽
2.5.2. 暴力法解决
- 对于每一根柱子,都分别向左向右遍历,找到第一根小于当前柱子高度的柱子,记录其序号。
- 当前最大面积:S=(right-left+1)*height
1 |
|
2.5.3. 递增栈
1 |
|
1 |
|
2.6. 第六第七题
- 简单省略
2.7. 第八题:统计单词的覆盖次数
2.8. 第九题:最长连续子序列
- 给定无序数组nums,求nums的最长连续序列的长度。
2.8.1. 暴力法
2.8.2. 排序、遍历计数
- 对所有数字进行排序(无需剔除重复数)
从最小的开始遍历,和前一个数连续(即等于前一个数加1)则计数加1,不连续则判断是否是最长连续,并重新开始计数
2.9. 第十题:有效的数独
- 检查数独的有效性
2.9.1. 暴力法
- 分别在每行、每列、每个block内对于每个数字判断有无重复出现
- 用count记录数字出现次数,大于1返回false
- 三重循环,时间复杂度O(n^3),空间复杂度O(1)
2.9.2. 用数组记录(hash表)
- 对于每行、每列、每个block用一个数组记录每个数字是否出现
- 出现过的数字在数组内记为1,再出现就返回false,二重循环,时间复杂度O(n^2),空间复杂度O(n)
3. 第三次作业
3.1. 第一题:重排链表
- 给定 n个数字(n未知)组成一个链表,然后给定一个 x 作为基准(x 不一定在链表中)。你需要对链表进行分隔,使得所有小于 x 的节点都在大于或等于 x 的节点之前。
- 你应当保留两个分区中每个节点的初始相对位置。
3.1.1. 实现结构
3.2. 第二题:加密计算接口
- 现在我们需要对外提供一个加密接口以满足定制系统的特殊计算任务。该接口为 int encrypt(func,int,int) ,其中 func 是外部调用函数,传入encrypt的一个函数指针typedef int(*func)(int, int)该接口的作用对外部提供的计算进行参数的调整加密(实际上外部调用者并不知道内部加密实现),并返回各种计算指令的结果。
3.2.1. 具体实现
3.3. 第三题:合并k个链表
- 给定k个升序链表,使用链表的结构将其合并
- 每行输入对应一个排过序的链表数据,输出合并后的升序序列
3.3.1. 基本思路
- 思路一:第一次把两个链表合并为ans,接下去把ans和剩余链表中的一个合并,最后ans就是答案
- 思路二:同时合并所有链表,比较所有链表当前位置中的所有节点大小,选取一个放入ans,直到所有链表中的节点都被选用了
- 读取链表:一次getline之后去分割 或者 用cin一个一个读取
3.3.2. 两两合并
- 第一种合并:
1 |
|
1 |
|
- 用分治的思想合并所有的链表
1 |
|
3.3.3. 同时合并(最小堆)
- 先把所有链表的第一个元素放入最小堆
- 每次弹出最小堆堆顶的元素
- 再把堆顶元素的下一个元素放入最小堆
- 直到堆中没有元素
1 |
|
3.4. 第四题:双向链表
1 |
|
3.4.1. 具体实现
1 |
|
- 详细见PPT
3.5. 第五题:矩阵乘法
3.5.1. 解决方案
- 输入的处理
- 对于所有的输入先按照字符型矩阵来进行输入,因为可能会因为第二个矩阵为非数值型矩阵需要继续转化为字符型矩阵
- 矩阵乘法处理
- 分别对应两个处理办法
- 一个处理数值型矩阵的乘法,一个处理字符型矩阵的乘法(或者是构造元素之间的乘法和加法)
- 值得注意的是按照数值型处理的过程结束之后,整型的数据要转化为整型
- 输出处理
- 对于输出的处理就直接按照字符型矩阵进行处理即可
3.5.2. 详见文件
4. 第四次作业
- 面向对象编程
4.1. 简单工厂
- 使用虚函数
4.2. 汉堡问题:装饰者模式
- 具体重载一个类
4.3. 擂台赛
- 纯虚函数定义方法
- pk()作为友元函数可以访问所有的内部的变量
4.4. 第四题:XO题
- 局部性检查即可
4.5. 第五题:汽车调研题
- 设计一下类的情况
4.6. 停车场问题
- 可以想象成一个内存分配的问题
4.7. 银行账户模拟
- 开闭原则和设计
4.8. 商品每日销售额
- 折扣需要注意
4.9. MyString类
4.10. TomAndJerry
- 简单的设计一下即可
5. 第一次考试
- long long ll :运行中越界
- 反复进行套娃操作
2020-C++高级程序设计-作业总结
https://spricoder.github.io/2020/07/01/2020-C-plus-plus-advanced-programming/2020-C-plus-plus-advanced-programming-%E4%BD%9C%E4%B8%9A%E6%80%BB%E7%BB%93/