求子数组最大值最小值之差小于或者等于num的算法

love蕾2012 2017-02-17 12:09:27
最大值减去最小值小于或等于 k 的子数组数量
给定数组 arr 和整数 k,共返回有多少个子数组满足如下情况:
max(arr[i..j]) - min(arr[i..j]) <= k
max(arr[i..j])表示子数组 arr[i..j]中的最大值,min(arr[i..j])表示子数组 arr[i..j]中的最小值。
【要求】
如果数组长度为 N,请实现时间复杂度为 O(N)的解法。

public static int getNum_2(int[] arr, int k){
int res = 0;
int left = 0;//左边界
int right = 0;//右边界
LinkedList<Integer> qmin= new LinkedList<Integer>();//最小值队列 递增
LinkedList<Integer> qmax= new LinkedList<Integer>();//最大值队列 递减
while(left<arr.length){
while (right<arr.length){
while(!qmin.isEmpty()&&arr[qmin.peekLast()]>=arr[right]){//
qmin.pollLast();
}
qmin.add(right);
while(!qmax.isEmpty()&&arr[qmax.peekLast()]<=arr[right]){
qmax.pollLast();
}
qmax.add(right);
if(arr[qmax.peekFirst()]-arr[qmin.peekFirst()]>k){//不符合要求
res += right-left; //清算之前一共有多少个子数组符合要求
break;
}
right++;//符合要求 右边界累加 子数组累加
}
//左边界移动之前先判断最小值 和 最大值队列中第一个是否为左边界 如果相等则移除
if(left==qmin.peekFirst()){
qmin.pollFirst();
}
if(left==qmax.peekFirst()){
qmax.pollFirst();
}
left++;
}
return res;
}

网上看到的一个算法,但是对于测试{3,1,2,4}却没有通过。
是我哪里错了么?
...全文
507 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
weixin_37524475 2017-02-17
  • 打赏
  • 举报
回复
k 你输入参数是多少
love蕾2012 2017-02-17
  • 打赏
  • 举报
回复
引用 10 楼 bree06 的回复:
[quote=引用 9 楼 u012156919 的回复:] [quote=引用 8 楼 bree06 的回复:] 时间复杂度为 O(N) 才是本题的关键, 很明显你搜的方法不满足要求.
这个算法是符合要求的。双端队列的操作是O(1), 数组里面的元素最多只会进出一次qmax和qmin.[/quote]你就简单的在内while循环里加一个计数器, 最里层的两个while就算给他忽略, 他的时间复杂度也要大于等于N[/quote] 时间复杂度的计算不是这么来的,主要看数据在内存中的移动变化的平均值,比较是相对于移动是忽略不计的。
引用 11 楼 bree06 的回复:
子数组arr[i..j]是原数组连续的子数组吗? 感觉应该是下标连续才会对. 如有arr = {11, 2, 6, 4, 54, 6, 71, 8, 9, 10}; k = 3; 那么结果应该是{6, 4}, {8, 9}, {9, 10}, {8, 9, 10}, 不知道你运行出来的结果是否为这样.
我感觉应该是有序这个算法才有效,找一个无序同样有效的方法,不然这个算法的时间就不会是O(N)
bree06 2017-02-17
  • 打赏
  • 举报
回复
子数组arr[i..j]是原数组连续的子数组吗? 感觉应该是下标连续才会对. 如有arr = {11, 2, 6, 4, 54, 6, 71, 8, 9, 10}; k = 3; 那么结果应该是{6, 4}, {8, 9}, {9, 10}, {8, 9, 10}, 不知道你运行出来的结果是否为这样.
bree06 2017-02-17
  • 打赏
  • 举报
回复
引用 9 楼 u012156919 的回复:
[quote=引用 8 楼 bree06 的回复:] 时间复杂度为 O(N) 才是本题的关键, 很明显你搜的方法不满足要求.
这个算法是符合要求的。双端队列的操作是O(1), 数组里面的元素最多只会进出一次qmax和qmin.[/quote]你就简单的在内while循环里加一个计数器, 最里层的两个while就算给他忽略, 他的时间复杂度也要大于等于N
love蕾2012 2017-02-17
  • 打赏
  • 举报
回复
引用 8 楼 bree06 的回复:
时间复杂度为 O(N) 才是本题的关键, 很明显你搜的方法不满足要求.
这个算法是符合要求的。双端队列的操作是O(1), 数组里面的元素最多只会进出一次qmax和qmin.
bree06 2017-02-17
  • 打赏
  • 举报
回复
时间复杂度为 O(N) 才是本题的关键, 很明显你搜的方法不满足要求.
love蕾2012 2017-02-17
  • 打赏
  • 举报
回复
引用 5 楼 frank_lee_cn 的回复:
“直接复制过来”没问题,我也常这么干。 问题是现在出错了,你何不利用这个机会,用代码跟踪工具跟踪代码的执行,自己找出哪里错了。 毕竟只有几行代码,自己除错不是挺爽的吗?
谢谢!
love蕾2012 2017-02-17
  • 打赏
  • 举报
回复
引用 5 楼 frank_lee_cn 的回复:
“直接复制过来”没问题,我也常这么干。 问题是现在出错了,你何不利用这个机会,用代码跟踪工具跟踪代码的执行,自己找出哪里错了。 毕竟只有几行代码,自己除错不是挺爽的吗?
正解,这样还有利于理解算法,咋早没想到,too young,too simple
Frank6600 2017-02-17
  • 打赏
  • 举报
回复
“直接复制过来”没问题,我也常这么干。 问题是现在出错了,你何不利用这个机会,用代码跟踪工具跟踪代码的执行,自己找出哪里错了。 毕竟只有几行代码,自己除错不是挺爽的吗?
love蕾2012 2017-02-17
  • 打赏
  • 举报
回复
引用 3 楼 frank_lee_cn 的回复:
你应该使用代码跟踪工具跟踪代码的执行,自己找出哪里错了。 注:代码跟踪工具在Eclipse这类IDE中就有
其实这段是一个算法的求解,很多网站上包括书上都是这样的,我直接复制过来,但是结果却不对。 我就给蒙圈了
Frank6600 2017-02-17
  • 打赏
  • 举报
回复
你应该使用代码跟踪工具跟踪代码的执行,自己找出哪里错了。 注:代码跟踪工具在Eclipse这类IDE中就有
love蕾2012 2017-02-17
  • 打赏
  • 举报
回复
引用 1 楼 weixin_37524475 的回复:
k 你输入参数是多少
参数可以随便设置比如2,把所有可能都列出来结果应该是9吧,为什么算法出来的是6呢? 难道是我哪里理解的不对?

62,628

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧