题目:给定一个数组和滑动窗体的大小,请找出全部滑动窗体里的最大值。


举例说明

  比如,假设输入数组{2,3,4,2,6,2,5,1}及滑动窗体的大小。那么一共存在6个滑动窗体,它们的最大值分别为{4,4,6,6,6,5}。

解题思路

  假设採用蛮力法,这个问题似乎不难解决:能够扫描每个滑动窗体的全部数字并找出当中的最大值。假设滑动窗体的大小为k,须要O(k)时间才干找出滑动窗体里的最大值。对于长度为n的输入数组,这个算法总的时间复杂度是O(nk)。

  实际上一个滑动窗体能够看成是一个队列。当窗体滑动时,处于窗体的第一个数字被删除,同一时候在窗体的末尾加入一个新的数字。

这符合队列的先进先出特性。

假设能从队列中找出它的最大数,这个问题也就攻克了。

  在面试题21中。我们实现了一个能够用O(1)时间得到最小值的栈。相同,也能够用O(1)时间得到栈的最大值。同一时候在面试题7中,我们讨论了怎样用两个栈实现一个队列。

综合这两个问题的解决方法,我们发现假设把队列用两个栈实现,因为能够用O(1)时间得到栈中的最大值。那么也就能够用O(1)时间得到队列的最大值,因此总的时间复杂度也就降到了O(n)。

  我们能够用这种方法来解决这个问题。

只是这样就相当于在一轮面试的时间内要做两个面试题,时间未必够用。再来看看有没有其他的方法。

  以下换一种思路。我们并不把滑动窗体的每个数值都存入队列中,而仅仅把有可能成为滑动窗体最大值的数值存入到一个两端开口的队列。接着以输入数字{2,3,4,2,6,2,5,1}为例一步分析。

  数组的第一个数字是2,把它存入队列中。第二个数字是3.因为它比前一个数字2大,因此2不可能成为滑动窗体中的最大值。

2先从队列里删除,再把3存入到队列中。此时队列中仅仅有一个数字3.针对第三个数字4的步骤相似,终于在队列中仅仅剩下一个数字4.此时滑动窗体中已经有3个数字。而它的最大值4位于队列的头部。

  接下来处理第四个数字2。2比队列中的数字4小。当4滑出窗体之后2还是有可能成为滑动窗体的最大值,因此把2存入队列的尾部。

如今队列中有两个数字4和2,当中最大值4仍然位于队列的头部。

  下一个数字是6.因为它比队列中已有的数字4和2都大,因此这时4和2已经不可能成为滑动窗体中的最大值。先把4和2从队列中删除。再把数字6存入队列。这个时候最大值6仍然位于队列的头部。

  第六个数字是2.因为它比队列中已有的数字6小,所以2也存入队列的尾部。此时队列中有两个数字,当中最大值6位于队列的头部。

  接下来的数字是5.在队列中已有的两个数字6和2里。2小于5。因此2不可能是一个滑动窗体的最大值,能够把它从队列的尾部删除。删除数字2之后,再把数字5存入队列。此时队列里剩下两个数字6和5,当中位于队列头部的是最大值6.

  数组最后一个数字是1。把1存入队列的尾部。注意到位于队列头部的数字6是数组的第5个数字,此时的滑动窗体已经不包含这个数字了,因此应该把数字6从队列删除。那么怎么知道滑动窗体是否包含一个数字?应该在队列里存入数字在数组里的下标,而不是数值。当一个数字的下标与当前处理的数字的下标之差大于或者等于滑动窗体的大小时。这个数字已经从滑动窗体中滑出,能够从队列中删除了。

代码实现

import java.util.*;

public class Test65 {
private static List<Integer> maxInWindows(List<Integer> data, int size) {
List<Integer> windowMax = new LinkedList<>(); // 条件检查
if (data == null || size < 1 || data.size() < 1) {
return windowMax;
} Deque<Integer> idx = new LinkedList<>(); // 窗体还没有被填满时。找最大值的索引
for (int i = 0; i < size && i < data.size(); i++) {
// 假设索引相应的值比之前存储的索引值相应的值大或者相等,就删除之前存储的值
while (!idx.isEmpty() && data.get(i) >= data.get(idx.getLast())) {
idx.removeLast();
} // 加入索引
idx.addLast(i);
} // 窗体已经被填满了
for (int i = size; i < data.size(); i++) {
// 第一个窗体的最大值保存
windowMax.add(data.get(idx.getFirst())); // 假设索引相应的值比之前存储的索引值相应的值大或者相等。就删除之前存储的值
while (!idx.isEmpty() && data.get(i) >= data.get(idx.getLast())) {
idx.removeLast();
} // 删除已经滑出窗体的数据相应的下标
if (!idx.isEmpty() && idx.getFirst() <= (i - size)) {
idx.removeFirst();
} // 可能的最大的下标索引入队
idx.addLast(i);
} // 最后一个窗体最大值入队
windowMax.add(data.get(idx.getFirst())); return windowMax; } private static List<Integer> arrayToCollection(int[] array) {
List<Integer> result = new LinkedList<>();
if (array != null) {
for (int i : array) {
result.add(i);
}
} return result;
} public static void main(String[] args) { // expected {7};
List<Integer> data1 = arrayToCollection(new int[]{1, 3, -1, -3, 5, 3, 6, 7});
System.out.println(data1 + "," + maxInWindows(data1, 10)); // expected {3, 3, 5, 5, 6, 7};
List<Integer> data2 = arrayToCollection(new int[]{1, 3, -1, -3, 5, 3, 6, 7});
System.out.println(data2 + "," + maxInWindows(data2, 3)); // expected {7, 9, 11, 13, 15};
List<Integer> data3 = arrayToCollection(new int[]{1, 3, 5, 7, 9, 11, 13, 15});
System.out.println(data3 + "," + maxInWindows(data3, 4)); // expected {16, 14, 12};
List<Integer> data5 = arrayToCollection(new int[]{16, 14, 12, 10, 8, 6, 4});
System.out.println(data5 + "," + maxInWindows(data5, 5)); // expected {10, 14, 12, 11};
List<Integer> data6 = arrayToCollection(new int[]{10, 14, 12, 11});
System.out.println(data6 + "," + maxInWindows(data6, 1)); // expected {14};
List<Integer> data7 = arrayToCollection(new int[]{10, 14, 12, 11});
System.out.println(data7 + "," + maxInWindows(data7, 4));
}
}

执行结果

特别说明

欢迎转载,转载请注明出处【http://blog.csdn.net/DERRANTCM/article/details/46872411

【剑指Offer学习】【面试题65:滑动窗体的最大值】的更多相关文章

  1. 【剑指offer】面试题 65. 不用加减乘除做加法

    面试题 65. 不用加减乘除做加法 题目描述 题目:写一个函数,求两个整数之和,要求在函数体内不得使用+.-.*./四则运算符号. Java 实现 public class Solution {    ...

  2. 《剑指offer》面试题65. 不用加减乘除做加法

    问题描述 写一个函数,求两个整数之和,要求在函数体内不得使用 "+"."-"."*"."/" 四则运算符号. 示例: 输 ...

  3. 《剑指offer》面试题59 - II. 队列的最大值

    问题描述 请定义一个队列并实现函数 max_value 得到队列里的最大值,要求函数max_value.push_back 和 pop_front 的均摊时间复杂度都是O(1). 若队列为空,pop_ ...

  4. 【剑指Offer学习】【全部面试题汇总】

    剑指Offer学习 剑指Offer这本书已经学习完了.从中也学习到了不少的东西,如今做一个总的文件夹.供自已和大家一起參考.学如逆水行舟.不进则退.仅仅有不断地学习才干跟上时候.跟得上技术的潮流! 全 ...

  5. 【剑指Offer学习】【所有面试题汇总】

    剑指Offer学习 剑指Offer这本书已经学习完了,从中也学习到了不少的东西,现在做一个总的目录,供自已和大家一起参考,学如逆水行舟,不进则退.只有不断地学习才能跟上时候,跟得上技术的潮流! 所有代 ...

  6. 剑指Offer——滴滴笔试题+知识点总结

    剑指Offer--滴滴笔试题+知识点总结 情景回顾 时间:2016.9.18 15:00-17:00 地点:山东省网络环境智能计算技术重点实验室 事件:滴滴笔试   总体来说,滴滴笔试内容体量不算多, ...

  7. 剑指Offer——网易笔试题+知识点总结

    剑指Offer--网易笔试题+知识点总结 Fibonacci package cn.edu.ujn.nk; import java.util.ArrayList; import java.util.S ...

  8. 剑指Offer——咪咕笔试题+知识点总结

    剑指Offer--咪咕笔试题+知识点总结 情景回顾 时间:2016.10.09 15:00-16:30 地点:山东省网络环境智能计算技术重点实验室 事件:咪咕笔试 知识点总结 1.Html设置格式贵阳 ...

  9. 剑指Offer——迅雷笔试题+知识点总结

    剑指Offer--迅雷笔试题+知识点总结 情景回顾 时间:2016.9.19 19:00-21:00 地点:山东省网络环境智能计算技术重点实验室 事件:迅雷笔试 总体来说,迅雷笔试内容体量不算多,主要 ...

  10. 《剑指offer》面试题39 二叉树的深度(java)

    摘要: 今天翻到了<剑指offer>面试题39,题目二中的解法二是在函数的参数列表中通过指针的方式进行传值,而java是没有指针的,所以函数要进行改造.然而我翻了下别人的java版本(我就 ...

随机推荐

  1. JDK1.8中的Stream详解

    Stream简介 Stream 作为 Java 8 的一大亮点,它与 java.io 包里的 InputStream 和 OutputStream 是完全不同的概念.它也不同于 StAX 对 XML ...

  2. PyQt5实现第一个桌面应用程序

    import sysfrom PyQt5.QtWidgets import QApplication,QWidget,QDialogfrom PyQt5.QtCore import Qt if __n ...

  3. 笔试算法题(08):输出倒数第K个节点

    出题:输入一个单向链表,要求输出链表中倒数第K个节点 分析:利用等差指针,指针A先行K步,然后指针B从链表头与A同步前进,当A到达链表尾时B指向的节点就是倒数第K个节点: 解题: struct Nod ...

  4. C++ typedef用法小结 (转载)

    声明:本文转自charley_yang,点击此处查看原文 第一.四个用途 用途一: 定义一种类型的别名,而不只是简单的宏替换.可以用作同时声明指针型的多个对象.比如:char* pa, pb; // ...

  5. 零基础入门学习Python(31)--永久存储:腌制一缸美味的泡菜

    知识点 pickle( 泡菜 ) 模块介绍: pickle模块作用是持久化的储存数据. 在Python程序运行中得到了一些字符串.列表.字典等数据,想要长久的保存下来,方便以后使用, 而不是简单的放入 ...

  6. python爬虫入门02:教你通过 Fiddler 进行手机抓包

    哟~哟~哟~ hi起来 everybody 今天要说说怎么在我们的手机抓包 通过 python爬虫入门01:教你在Chrome浏览器轻松抓包 我们知道了 HTTP 的请求方式 以及在 Chrome 中 ...

  7. MySQL数据库初识

    认识数据库 1 什么是数据(Data) 描述事物的符号记录称为数据,描述事物的符号既可以是数字,也可以是文字.图片,图像.声音.语言等,数据由多种表现形式,它们都可以经过数字化后存入计算机 在计算机中 ...

  8. LeetCode1---两数之和

    import java.util.Arrays;import java.util.HashMap;import java.util.Map; /** *功能描述 :两数之和 * @author lkr ...

  9. 如何判断CPU、内存、磁盘的性能瓶颈?

    1.如何判断CPU.内存.磁盘的瓶颈? CPU瓶颈1) 查看CPU利用率.建议CPU指标如下 a) User Time:65%-70% b) System Time:30%-35% c) Idle:0 ...

  10. spark streaming 踩过的那些坑

      系统背景 spark streaming + Kafka高级API receiver 目前资源分配(现在系统比较稳定的资源分配),独立集群 --driver-memory 50G   --exec ...