简介
滑动窗口最大值,leetcode 239,我觉得我这个方法的时间还不错,所以分享一下我的思路。
另外我的内存内用确实一直不是很优秀,在这方面有研究的小伙伴还希望让我学习一下。
来看一下我的提交:
用时我是满意的,但是内存占的忒多了。
思考过程
我说一下我的思考过程
首先这是一道典型的滑动窗口题目,那么一定有一个left遍历,然后另一个right用left+k-1来定位。
然后,不可避免就是一定要遍历每一个k长度的数组,知道left+k-1到了nums.length,然后找到k个数的最大值,写入res数组。
那么先别想优化的事情,先写一个findMax函数:
public int findMax(int left, int right, int[] nums) {
int res = -1;
for (int i = left; i <= right; i++) {
if (nums[i] > res) {
res = nums[i];
}
}
return res;
}
这里没什么纠结的。
- 优化
有了想法先别写代码,一看我就觉得时间会超。
那么开始优化。
首先我们建立一个小模型,这样方便我讲清楚
[k1,k2,k3] k4 (假设这是k=3的情况)
,当添加进来新的元素k4的时候,一定会将原来的left值k1抛弃掉,那么如果上一个窗口的最大值是k1,毫无疑问要重新用findMax来寻找,那么如果上一个的窗口最大值不是k1的话,很明显我们不需要调用findMax来遍历寻找最大值。
ok,我们已经找到了优化的第一个思路。
然后我仔细一想,我还很贪心,希望继续深化我们的优化方案,我们将lastWindowMax的窗口的位置记下来,继续将部分findMax操作简化为了两个数字的比大小操作。
扫描二维码关注公众号,回复:
9299568 查看本文章
算法简述
好了这样就是我的算法思路了,来看具体的思路
existed用来记录lastWindowMax的位置:0代表窗口最左边的,以此类推
/*
* 当left+k-1<nums.length
* 查看existed,if( >0 ):
* if( lastWindowMax>nums[left+k-1] ) {existed--;res添加lastWindowMax }
* else { existed = 2 res添加nums[left+k-1]; 更新lastWindowMax }
* else: 计算k窗口最大值,更新existed,更新lastWindowMax
* left++
* 循环到第3步
* */
当然findMax就需要修改为返回max值和对应位置的两个值了。
我用数组结构。
代码
public int[] maxSlidingWindow1(int[] nums, int k) {
int len = nums.length;
if (len == 0) {
return new int[]{};
}
int existed = 0;
int lastWindowMax = -1;
int left = 0;
int[] res = new int[len-k+1];
while (left + k - 1 < len) {
int tmp = nums[left + k - 1];
if (existed > 0) {
if (lastWindowMax > tmp) {
existed--;
res[left] = lastWindowMax;
} else {
existed = 2;
res[left] = tmp;
lastWindowMax = tmp;
}
} else {
int[] arr = findMax(left, left + k - 1, nums);
res[left] = arr[0];
lastWindowMax = arr[0];
existed = arr[1];
}
left++;
}
return res;
}
public int[] findMax(int left, int right, int[] nums) {
int res = -1;
int loc = 0;
for (int i = left; i <= right; i++) {
if (nums[i] > res) {
res = nums[i];
loc = i-left;
}
}
return new int[]{res, loc};
}
大家共勉~~
欢迎指正,和新想法