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


举例说明

  比如,假设输入数组{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. vc中无符号字符数组保存的内存值转换为无符号整数保存

    分为三步,第一步,将进行指针类型转换:第二步,进行*地址运算:第三部赋值. 贴代码如下: unsigned char numberPlain [4] = {0}; UINT32 MaxNumber = ...

  2. 2. 区分散列的 undef 值, 和手动赋值 0 不一样。1. 使用exists函数,散列中有这个键(必须是keys %hash 有这结果),则返回真值,

    2. 123 my %vertical_alignment;    124 $vertical_alignment{"subscripting"} = 0;    125 unle ...

  3. 关于nested exception is org.apache.ibatis.binding.BindingException:Parameter '***' not found报错解决

    几天晚上遇到的奇怪的问题  传入的参数名一直没有变   但是从mapper到xml似乎有一个找不到参数的报错,实际上只要在Mapper接口形参前加“@Param(“形参名称”)”就可以了

  4. Oracle存储过程和程序包

    一.为什么要用存储过程? 如果在应用程序中经常需要执行特定的操作,可以基于这些操作简历一个特定的过程.通过使用过程可以简化客户端程序的开发和维护,而且还能提高客户端程序的运行性能. 二.过程的优点? ...

  5. heroku安装(win7x64)

    Jdk安装:官网地址 http://www.oracle.com/technetwork/java/javase/downloads/index-jsp-138363.html下载要安装的jdk版本. ...

  6. 13Spring通过注解配置Bean(1)

    配置Bean的形式:基于XML文件的方式:基于注解的方式(基于注解配置Bean:基于注解来装配Bean的属性) 下面介绍基于注解的方式来配置Bean. ——组件扫描(component scannin ...

  7. uva 327 - Evaluating Simple C Expressions

     Evaluating Simple C Expressions  The task in this problem is to evaluate a sequence of simple C exp ...

  8. 高阶函数 map,reduce, filter的用法

    1. map 用法 def fun_C(x): """求平方""" return x ** 2 result = map(fun_C, my ...

  9. chrome webstore

    chrome webstore https://chrome.google.com/webstore/detail/set-character-encoding/bpojelgakakmcfmjfil ...

  10. topcoder SRM 639 div2

    见这里 http://ygdtc.sinaapp.com/?p=257