继续第二期,这部分的三道题变得比较复杂了。
Qus4 游历魔法王国
试题描述
魔法王国一共有n个城市,编号为0~n-1号,n个城市之间的道路连接起来恰好构成一棵树。
小易现在在0号城市,每次行动小易会从当前所在的城市走到与其相邻的一个城市,小易最多能行动L次。
如果小易到达过某个城市就视为小易游历过这个城市了,小易现在要制定好的旅游计划使他能游历最多的城市,请你帮他计算一下他最多能游历过多少个城市(注意0号城市已经游历了,游历过的城市不重复计算)。
输入描述:
输入包括两行,第一行包括两个正整数
n(2 ≤ n ≤ 50)和L(1 ≤ L ≤ 100),表示城市个数和小易能行动的次数。
第二行包括n-1个整数parenti, 对于每个合法的i(0 ≤ i ≤ n - 2),在(i+1)号城市和parent[i]间有一条道路连接。
输出描述:
输出一个整数,表示小易
最多能游历的城市数量。
示例1
输入
5 2
0 1 2 3输出
3
试题分析
试题最后抽象成求树的最大深度。
输入描述中第二行 第二行包括n-1个整数parent[i](0 ≤ parent[i] ≤ i), 对于每个合法的i(0 ≤ i ≤ n - 2),在(i+1)号城市和parent[i]间有一条道路连接,绕了半天,其实是描述树的形状。
例如测试用例:
10 10
0 3 1 3 0 5 2 7 5
对应的关系如下:
| Tables | Col 1 | Col 2 | Col 3 | Col 4 | Col 5 | Col 6 | Col 7 | Col 8 | Col 9 |
|---|---|---|---|---|---|---|---|---|---|
| 子节点(i) | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| 父节点(parent[i]) | 0 | 3 | 1 | 3 | 0 | 5 | 2 | 7 | 5 |
生成的树:
树的结构有了之后,就只需要根据树的最大深度depth与可走的最大步数L之间的关系来判断最终的游历城市数量。
- 当
depth ≥ L时,那么能够游历的城市数即L + 1(因为出发位置在得0号城市,算是已经游历的城市); - 当
depth < L时,即需要走重复的路。显而易见,返回需要走两遍相同的路径。最优化的行走方案是将旅程分为两个部分,一个部分为走到最大深度depth,另一部分为走重复路的短路径(L-depth)/2(即除了树的大深度外的步数,由于折返故除以2)。
代码实现
1 | function main(argument) { |
反思
- 代码中有一项未判断,即当步数
L>(depth + (L-depth)/2)时,部署应该为城市数n; - 在生成树的过程中,由于遍历过程中可能部分节点在未生成时引用会出现
undefined问题,故引入判断,在第15行处再循环一次; - 第20行处实用了
ES6中的扩展运算符( ... ),在学习ES6时再继续详细解答; - 其实对于生成树与计算最大深度还是不太明白,该抽时间补一补数据结构了。
Qus5 重排数列
试题描述
小易有一个长度为N的正整数数列A = {A[1], A[2], A[3]..., A[N]}。
牛博士给小易出了一个难题:
对数列A进行重新排列,使数列A满足所有的A[i] * A[i + 1](1 ≤ i ≤ N - 1)都是4的倍数。
小易现在需要判断一个数列是否可以重排之后满足牛博士的要求。
输入描述:
输入的第一行为数列的个数
t(1 ≤ t ≤ 10),
接下来每两行描述一个数列A,第一行为数列长度n(1 ≤ n ≤ 10^5)
第二行为n个正整数A[i](1 ≤ A[i] ≤ 10^9)
输出描述:
对于每个数列输出一行表示是否可以满足牛博士要求,如果可以输出
Yes,否则输出No。
示例1
输入
2
3
1 10 100
4
1 2 3 4输出
Yes
No
试题分析
根据题意,将数列A中的数字分为三类:
n4 : 可以被4整除的数
n2 : 可以被2整除但不可以被4整除的数
n1 : 不可以被2整除的数
那么如果要满足题目要求即A[i] * A[i + 1](1 ≤ i ≤ N - 1)都是4的倍数,则必须以下两种情况:
- 数字
n1的两侧都要有n4(数列第一个或最后一个只需满足一侧存在n4即可); - 数字
n2的两侧要存在n2或者n4;
那么对条件进行简化,数组A可能出现的情况:
n4 > = n1—— 满足题目要求;n4 = n1 - 1 && n4 + n1 = A.length—— 数列第一个与最后一个均为n1,满足题目要求;n4 < n1 - 1—— 不满足
这样就很清晰了,详情见代码实现
代码实现
1 | function main(argument) { |
反思
- 最开始的思路是按照题意,数列中的所有数字互相相乘,得出新的数列。判断新的数列中的数组是否能被4整除,如果得到的结果大于原数组length - 1 即满足条件,这样能通过最开始的两组数列的测验,因为开始的数列相对比较短(4个以下);
- 写了一个取模的函数,参数采用
json格式;
Qus6 最长公共子括号序列
试题描述
一个合法的括号匹配序列被定义为:
- 空串
""是合法的括号序列 - 如果
"X"和"Y"是合法的序列,那么"XY"也是一个合法的括号序列 - 如果
"X"是一个合法的序列,那么"(X)"也是一个合法的括号序列 - 每个合法的括号序列都可以由上面的规则生成
例如"","()", "()()()", "(()())", "(((()))"都是合法的。
从一个字符串S中移除零个或者多个字符得到的序列称为S的子序列。
例如"abcde"的子序列有"abe","","abcde"等。
定义LCS(S,T)为字符串S和字符串T最长公共子序列的长度,即一个最长的序列W既是S的子序列也是T的子序列的长度。
小易给出一个合法的括号匹配序列S,小易希望你能找出具有以下特征的括号序列t:
T跟S不同,但是长度相同T也是一个合法的括号匹配序列LCS(S, T)是满足上述两个条件的T中最大的
因为这样的T可能存在多个,小易需要你计算出满足条件的T有多少个。
如样例所示: S = "(())()",跟字符串S长度相同的合法括号匹配序列有:"()(())", "((()))", "()()()", "(()())",其中LCS( "(())()", "()(())" )为4,其他三个都为5,所以输出3.
输入描述:
输入包括字符串
S(4 ≤ |S| ≤ 50,|S|表示字符串长度),保证S是一个合法的括号匹配序列。
输出描述:
输出一个正整数,满足条件的
T的个数。
示例1
输入
(())()
输出
3
试题分析
很容易得出满足LCS(S , T)最大的S与T最长序列W的长度为S.length - 1。那么接下来的问题就很容易处理了。
将S中的任意一个字节抽离出来放到任意一个位置生成新的字符串T,通过合法性判断与去重,并且去除原字符串,得到的数组长度即为最终结果。
代码实现
1 | function main(str) { |
反思
- 通过数组的
堆栈方式来判断括号字符串是否合法,主要通过出栈方法array.pop()方法是否为空来判断(代码37行); - 因为经过遍历去重后的数组,肯定有一个和原数组一样,所以返回最终结果时不需要再对原数组进行去重处理,直接将返回的
length - 1即最后结果(代码37行); - 第10行的时候,犯了个低级错误,写错变量名,调试了很久才发现。。