题目一:好多鱼
牛牛有一个鱼缸。鱼缸里面已经有n条鱼,每条鱼的大小为fishSize[i] (1 ≤ i ≤ n,均为正整数),牛牛现在想把新捕捉的鱼放入鱼缸。鱼缸内存在着大鱼吃小鱼的定律。经过观察,牛牛发现一条鱼A的大小为另外一条鱼B大小的2倍到10倍(包括2倍大小和10倍大小),鱼A会吃掉鱼B。考虑到这个,牛牛要放入的鱼就需要保证:
1、放进去的鱼是安全的,不会被其他鱼吃掉
2、这条鱼放进去也不能吃掉其他鱼
鱼缸里面已经存在的鱼已经相处了很久,不考虑他们互相捕食。现在知道新放入鱼的大小范围minSize,maxSize,牛牛想知道有多少种大小的鱼可以放入这个鱼缸,
输入描述
输入数据包括3行.
第一行为新放入鱼的尺寸范围minSize,maxSize(1 ≤ minSize,maxSize ≤ 1000),以空格分隔。
第二行为鱼缸里面已经有鱼的数量n(1 ≤ n ≤ 50)
第三行为已经有的鱼的大小fishSizei,以空格分隔。
输出描述
输出有多少种大小的鱼可以放入这个鱼缸。考虑鱼的大小都是整数表示
输入例子
1 12
1
1
输出例子
3
解题思路
这基本就是个比较大小的问题,不过并不牵扯到排序。根据题目,池子里已经有一些鱼,并且每条鱼的大小已知,那么后面放进去的鱼有两种可能会互相吃掉:
1.后放进的鱼比里面的某些鱼大:后放进的鱼是这些鱼的 2~10 倍大;
2.后放进的鱼比里面的某些鱼小:里面的鱼是后放进鱼的 2~10 倍大;
用 size 代表后放进的鱼的大小,fishes[i] 代码里面的鱼的大小,则当:
1 : fish[i] 2 <= size <= fish[i] 10 ,此时后放进去的鱼会吃掉原有的鱼;
2 : size 2 <= fishes[i] <= size 10,此时原有的鱼会吃掉后放进的鱼;
这两个条件要同时不满足,才能保证不会有鱼被吃掉;
只要不是这两种情况,那么所有的鱼都可以存活,也就是满足:
(size > fishes[i] 10 || size < fishes[i] 2) && (fishes[i] > size 10 || fishes[i] < size 2 )
因为比较大小功能比较单一,可以抽象出一个 boolean compareTo(int fishSize,int[] fishes) 方法来,那么就有如下代码:
Java 实现(已AC)
1 | import java.util.Scanner; |
题目二:序列和
给出一个正整数N和长度L,找出一段长度大于等于L的连续非负整数,他们的和恰好为N。答案可能有多个,我我们需要找出长度最小的那个。
例如 N = 18 L = 2:
5 + 6 + 7 = 18
3 + 4 + 5 + 6 = 18
都是满足要求的,但是我们输出更短的 5 6 7
输入描述
输入数据包括一行:
两个正整数N(1 ≤ N ≤ 1000000000),L(2 ≤ L ≤ 100)
输出描述
从小到大输出这段连续非负整数,以空格分隔,行末无空格。如果没有这样的序列或者找出的序列长度大于100,则输出No
输入例子
18 2
输出例子
5 6 7
解题思路
这道题我昨晚模拟考试的时候并没有做出来,知道最后时间结束也只有 10% 的 case 通过测试。然后今天又奋战了一早晨,知道下午一点多才完全测试通过。
从输入描述来看输入的正整数会非常大,因此一定得考虑时间复杂度的问题,否则当输入的数为 1000000000 的时候会等待个十几秒乃至更久,所以其实我也是根据测试用例的提示一点点改进的,中间推翻了好几次之前的思路。
虽然输入数据很大,但是题目显示序列长度最长不能超过 100 ,这个数字利用起来,就能大幅度节省循环的时间。我们知道,若和为 m ,连续序列的长度为 n ,那么这个序列的起始数字肯定不会大于这些序列的平均值,所以 起始数字的范围最大到 m/n ;而序列起始值的最小范围也值得斟酌:m/n 是最大的可能值,既然是 n 个数字,又是连续的,那么第一个数字 至少要从 m/n-n/2 开始算起,例如和为 100 ,序列长度为 4,那么可能起始的值的最大值不会超过25,最小值不会小于 100/4-4/2 也就是 23 ;你可以用任何满足要求的数字和长度进行试验。
当然在当前长度可能找不到满足要求的序列,那么就需要增加序列的长度,然后重新计算起始值的最小最大范围。
Java 实现(已AC)
1 | import java.util.Scanner; |
做了两道题就已经感觉有点头昏脑涨了,果然算法题更加容易耗费脑细胞 ~~
感觉自己做算法题都是凭借逻辑性来做,对题目并没有整体性的认识和判断,比如题目属于什么类型,有什么可供参考的解题思路,所以我还是得多看看算法书啊。