拦截导弹
-
描述
-
某国为了防御敌国的导弹袭击,发展中一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于等于前一发的高度。某天,雷达捕捉到敌国导弹来袭。由于该系统还在试用阶段,所以只用一套系统,因此有可能不能拦截所有的导弹。
这题本身不难,但是在完成之后 我看到了更好的优化思路,整理了下收获不少,特别拿出来分享一下
首先明白题目的本质,题目需要查找一个数组中的最长严格递减序列,最基本的做法也就是对数组进行遍历, 遍历到第i个节点是,向前找比他小的节点,并且存储其中最大的长度加1,如果找不到比他小的,那就存储1,(作为一个新序列的开始)
对于楼主第一个问题 我构想的一个解决方案是在过程中存储的不仅仅是长度为n的序列的最小尾端值,而是挂一个长度为n序列的尾端的有序链表上去, 在最后存pre的时候 存的是长度n 与 对应链表的index, 这样是可以遍历出所有最大长度的序列的,复杂度为 O(n^2)
</pre><pre style="background-color:#2b2b2b;color:#a9b7c6;font-family:'SimSun';font-size:14pt;"><span style="color:#cc7832;background-color:#344134;">import</span><span style="color:#cc7832;"> </span>java.util.TreeMap<span style="color:#cc7832;">;
</span><span style="color:#cc7832;">import </span>java.util.Scanner<span style="color:#cc7832;">;
</span><span style="color:#cc7832;">
</span><span style="color:#629755;">/**
</span><span style="color:#629755;"> * Created by yueguang on 5/18/2015.
</span><span style="color:#629755;"> */
</span><span style="color:#cc7832;">public class </span>anti_missile_imp {
<span style="color:#cc7832;">public static void </span><span style="color:#ffc66d;">main</span>(String[] args){
<span style="background-color:#344134;">TreeMap</span><Integer<span style="color:#cc7832;">,</span>Integer> cacheMap = <span style="color:#cc7832;">new </span><span style="background-color:#344134;">TreeMap</span><Integer<span style="color:#cc7832;">, </span>Integer>()<span style="color:#cc7832;">;
</span><span style="color:#cc7832;">
</span><span style="color:#cc7832;"> </span>Scanner in = <span style="color:#cc7832;">new </span>Scanner(System.<span style="color:#9876aa;"><em>in</em></span>)<span style="color:#cc7832;">;
</span><span style="color:#cc7832;"> int</span>[] inputArray = <span style="color:#cc7832;">new int</span>[<span style="color:#6897bb;">21</span>]<span style="color:#cc7832;">;
</span><span style="color:#cc7832;"> int </span>groups = in.nextInt()<span style="color:#cc7832;">;
</span><span style="color:#cc7832;"> while</span>(groups--><span style="color:#6897bb;">0</span>){
<span style="color:#808080;">//读入数据
</span><span style="color:#808080;"> </span><span style="color:#cc7832;">int </span>missileCount = in.nextInt()<span style="color:#cc7832;">;
</span><span style="color:#cc7832;"> for</span>(<span style="color:#cc7832;">int </span>i = <span style="color:#6897bb;">0</span><span style="color:#cc7832;">; </span>i < missileCount <span style="color:#cc7832;">; </span>i++){
inputArray[i] = in.nextInt()<span style="color:#cc7832;">;
</span><span style="color:#cc7832;"> </span>}
<span style="color:#808080;">//处理数据
</span><span style="color:#808080;"> </span>cacheMap.clear()<span style="color:#cc7832;">;
</span><span style="color:#cc7832;"> </span>cacheMap.put(<span style="color:#6897bb;">1</span><span style="color:#cc7832;">,</span>inputArray[<span style="color:#6897bb;">0</span>])<span style="color:#cc7832;">;
</span><span style="color:#cc7832;">
</span><span style="color:#cc7832;"> for</span>(<span style="color:#cc7832;">int </span>i = <span style="color:#6897bb;">1</span><span style="color:#cc7832;">; </span>i < missileCount <span style="color:#cc7832;">;</span>i++){
<span style="color:#cc7832;">int </span>index= cacheMap.size()<span style="color:#cc7832;">;
</span><span style="color:#cc7832;"> int </span>terminal= <span style="color:#6897bb;">0</span><span style="color:#cc7832;">;
</span><span style="color:#cc7832;"> for</span>(<span style="color:#cc7832;">int </span>j = index <span style="color:#cc7832;">; </span>j > <span style="color:#6897bb;">0 </span><span style="color:#cc7832;">; </span>j--){
<span style="color:#cc7832;">if</span>(inputArray[i] < cacheMap.get(j)){
terminal = j<span style="color:#cc7832;">;
</span><span style="color:#cc7832;"> break;
</span><span style="color:#cc7832;"> </span>}
}
<span style="color:#cc7832;">int </span>temp=inputArray[i]<span style="color:#cc7832;">;
</span><span style="color:#cc7832;"> if</span>(index != cacheMap.size()){
temp = temp<cacheMap.get(terminal+<span style="color:#6897bb;">1</span>)?cacheMap.get(index+<span style="color:#6897bb;">1</span>):temp<span style="color:#cc7832;">;
</span><span style="color:#cc7832;"> </span>}
cacheMap.put(terminal+<span style="color:#6897bb;">1</span><span style="color:#cc7832;">,</span>temp)<span style="color:#cc7832;">;
</span><span style="color:#cc7832;">
</span><span style="color:#cc7832;"> </span>}
System.<span style="color:#9876aa;"><em>out</em></span>.println(cacheMap.size())<span style="color:#cc7832;">;
</span><span style="color:#cc7832;"> </span>}
}
}
这种方法相较于上一种方法的优越之处在于离散化了统计数据, 如果输入数列是一个严格不减序列的时候,这种方法也没办法避免O(n^2)的最坏时间,但是针对随机数列,时间复杂度有一个明显的下降,最优情况下为 O(n),如果输入数列是一个严格减序列
另外我们可以打印最长递减序列,这个需要通过额外的存储实现,我们可以针对节点存储preNode, 最后用递归的手段实现打印序列, 如 通过最大长度n 找到 对应的节点索引,递归前序节点,然后打印节点
比较复杂的是打印所有的最长序列,我构想的一个解决方案是在过程中存储的不仅仅是长度为n的序列的最小尾端值,而是挂一个长度为n序列的尾端的有序链表上去, 在最后存pre的时候 存的是长度n 与 对应链表的index, 这样是可以遍历出所有最大长度的序列的,这个我还没实践验证
最后感谢另外一位博主的思路分享 http://blog.csdn.net/joylnwang/article/details/6766317
2015年5月23日13:45:00 抱歉之前 弄错了概念, TreeMap的键值 才是有序的 现在修正了程序