Sex1-递归
1.部分同学针对于递归函数的理解不够深刻。可参考以下链接加以巩固复习。https://www.zhihu.com/question/31412436/answer/683820765?utm_source=wechat_session&utm_medium=social&utm_oi=931879418771615744
2.“6-5 递归实现顺序输出整数”。该题需顺序输出整数,而针对整数取余操作是按照从低位到高位的顺序,因此在递归过程中,需要先调用printdigits()函数,再printf()实现从高位到低位的输出。注意输出整数的输出顺序,需考虑个别样例(例如n为100000,0,1等)。
3.“6-6 判断满足条件的三位数”。该题可以在递归过程中从n开始依次递减直到100结束,判断区间内每个数是否符合题目要求。判断一个三位数n是否有两位重复,可以构建一个长度为10的数组arr,分别截取n对位个位、十位、百位并通过数组记录其数字是否重复(如arr[i]>=2则说明i在n中出现了两次)。
另:如有不明白的知识点或题目,请大家一定要及时和我沟通。
Sex1p-递归续
1 正整数拆分
本题目难度在于正整数拆分过程的输出。大部分同学都尝试了在拆分的过程中直接输出整数n,试想是否可以换成一种思路:用一个数组记录每次拆分的结果,在拆分过程中不需考虑输出,在单次拆分结束后统一输出。例如:
10=4+3+2+1 先用数组记录每次拆分的结果:array=[4,3,2,1]
10=1+1+1+1+1+1+1+1+1+1 每次拆分的结果:array=[1,1,1,1,1,1,1,1,1,1]
因此,问题就可以转换为如下两部分:
- 递归求取正整数拆分的数组表示。
- 对于每次求取的数组,进行格式化输出。
正向考虑正整数n的拆分有些困难,可以逆向思考:
假设不考虑n的大小,我们可以列举实现数组array=[n-1,n-1,…n-1,n-1,n-1]、[1,1,1,…,1,1,1]对应所有元素的和sum,判断sum与n的大小即可,大小关系分为以下三种情况:
- sum>n:数组之和大于该正整数,例如n=6,且array=[3,2,2],说明该样例不符,直接退出。
- sum==n:数组之和等于该正整数,例如n=6,且array=[3,2,1],说明该样例符合,需要进行格式化输出。
- sum<n:数组之和小于该正整数,例如n=6,且array=[3,2],说明该样例数据较少,需要进行进一步递归增加样例。
针对以上分析,array和n可以设置为全局变量,确定递归函数divisionInteger()参数有以下几个:
- array_len: 当前已经拆分的整数的个数,即当前记录的已经划分的数量
- sum: 当前已经划分整数的总和
- next_max_value: 根据样例输出可以看出,其划分的每项整数均不大于其前面一项(单调递减),因此需要一个参数记录并确定下一次递归时数组的最大值,该最大值不超过数组的最大值。
整理得,伪代码大致可以如下:
variable array[ARRAY_LENGTH];
integer n;
void divisionInteger(array_len, sum, next_max_value)
{
if sum>n:
return
else if sum==n:
格式化输出n及数组
else:
for i in range(next_max_value, 1):
array[array_len] = i //记录第array_len个数为i
divisionInteger(array_len+1, sum+i, i) //由于array添加了一个数,因此sum也需要加上,由于该数组是单调递减的,因此下一个数值需要限定为不大于i
}
针对以上代码, 可以进一步尝试剪枝,不详细介绍,同学们可以自行尝试。
PS:
本题仅要求输出正整数拆分,递归求整数划分个数也是比较有意思的方向,感兴趣的同学可以递推公式实现求整数划分个数。
2 求迷宫最短通道
参考思路:
本题利用深度优先遍历(DFS),寻找到能到达终点的所有可能路径对应的长度。然后记录最短路径并输出。
迷宫问题每走一步都有四种选择(上右下左),先选择一个方向,如果该方向能够走下去,那么就往这个方向走,当前位置切换为下一个位置,步长+1。如果不能走,则换个方向,如果所有方向都走不了,那么退出当前位置,到上一步的位置去,当前位置切换为上一步的位置,步长-1。一直这样执行下去,要么可以找到终点,要么所有的路径都没能到达终点。值得注意的是,为了求取最短路径,可以在终点时比较步长信息,取最短步长即可。
除此之外,广度优先遍历能够实现直接求取最短路径,可以自行探索。
专题课-模块化程序设计
本专题考察以下知识点:
- “完成M1要做的内务工作,即发送一条消息在屏幕上"Hello M2, I am M1\n" , 然后检查 M2 的任务是否完成”:因此,M1Task()的任务包括两部分:第一为完成对应的内务工作,第二为检查M2是否完成。
- “虚拟组员M1的内务工作别人是看不到的”:为保证其他模块无法调用对应的内务工作,需要将模块的内务工作单独列出为一个函数A(),可利用某关键词将该函数A()限定为仅能在该模块内访问。为使外部能够调用该模块的任务函数M1Task(),需要将该函数暴露出去。
- M*Task()函数,可以自行设定参数及返回值类型。
- 该系统限定文件写入模式为"w+",在管理员模式下输出到屏幕的签到信息,可以不必从文件中读取。
SEx3p-指针进阶续
2-5 定义带参数的宏“#define JH(a,b,t) t = a; a = b; b = t”,对两个参数a、b的值进行交换,下列表述中正确的是()。
- A. 不定义参数a和b将导致编译错误
- B. 不定义参数a、b、t将导致编译错误
解析:编译器不会检查宏参有没有定义,因此无论是否定义a、b、t都不导致编译错误。 - C. 不定义参数t将导致运行错误
解析:无论是否定义a、b、t都不导致编译错误。但是,不定义参数t将导致运行错误,因为交换两个数值需要一个变量来过度 - D. 不需要定义参数a、b、t类型
- 解析:宏里的参数不是变量,只是简单的替换,不需要定义类型。但是宏参只是达到替换的作用,不能定义它的类型,如果不定义,虽然不会导致编译错误,但是会出现运行错误。
2-7 下面说法中正确的()
- A. 若全局变量仅在单个C文件中访问,则可以将这个变量修改为静态全局变量,以降低模块间的耦合度
解析:变量分为全局变量和局部变量。局部变量和形参的作用域是函数内部,全局变量的作用域是整个文件。但可以通过声明一个extern的全局变量拓展全局变量的作用域,也可以通过定义一个static的全局变量限制这种拓展。 - B. 若全局变量仅由单个函数访问,则可以将这个变量改为该函数的静态局部变量,以降低模块间的耦合度
解析:如果全局变量仅仅由单个函数访问,不存在耦合度的问题 - C. 设计和使用访问动态全局变量、静态全局变量、静态局部变量的函数时,需要考虑变量生命周期问题
解析:动态全局变量、静态全局变量、静态局部变量的生命周期都为程序运行期间,其中静态局部变量的生存周期虽然为整个源程序,但是其作用域仍然与局部变量相同,当退出函数是,该变量还存在,但是不能使用。 - D. 静态全局变量使用过多,可那会导致动态存储区(堆栈)溢出
解析:局变量和静态变量都是存储在静态存储区,所以在递归调用是不会压栈,也不会造成堆栈溢出。
SEx4p - 指针续
- “6-1 用单向链表完成多项式运算”。本题考察链表的增删改查。注意输出格式需符合书写格式,建议如下的输出格式:。
系数 | 指数 | 是否首项 | 输出格式 |
---|---|---|---|
- | - | - | 正常输出 |
0 | - | - | 省略输出 |
1或-1 | 1 | 否 | 省略系数及指数:+x^1或-x^1–>+x或-x |
1或-1 | 1 | 是 | 省略系数、指数及前置加号:+x^1或-x^1–>x或-x |
正数k | 1 | 是 | 省略前置加号:+kx^1–>kx |
正数k | 0 | 否 | 省略x: +kx^0–>+k |
正数k | 0 | 是 | 省略x及前置加号:+k–>k |
负数k | 0 | - | 省略x: kx^0–>k |
另外,测试不通过时,建议尝试以下几种情况:
- 两多项式的指数都不相同,包括指数为0
- 常数(包括0)与1个多项式
- 一个多项式与一个常数(包括0)
- 两多项式的指数都为正数
- 两多项式的指数有正负不一样或一样
- 两多项式的项数不同,指数有正负不一样或一样
- 两多项式的项数和系数任意