日期:2020-10-13
作者:19届 LZ
标签:JAVA
题目描述
给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。
返回滑动窗口中的最大值。
进阶:
你能在线性时间复杂度内解决此题吗?
示例:
输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3
输出: [3,3,5,5,6,7]
解释:
滑动窗口的位置 最大值
--------------- -----
[1 3 -1] -3 5 3 6 7 3
1 [3 -1 -3] 5 3 6 7 3
1 3 [-1 -3 5] 3 6 7 5
1 3 -1 [-3 5 3] 6 7 5
1 3 -1 -3 [5 3 6] 7 6
1 3 -1 -3 5 [3 6 7] 7
解题思路:
为了达到线性时间复杂度,我们只能遍历有限次数组,所以可以将nums分成nums.length/k块,每块有k个数字.用数组left,right记录该位置到其所在块的最左(右)边中的最大元素.max(right[i],left[i+k-1])即为窗口内最大数
代码
class Solution { //暴力法,时间复杂度O(nk),一如既往超时
public int[] maxSlidingWindow(int[] nums, int k) {
if(k==1){
return nums;
}
int n=nums.length;
int max=0;
int []result=new int[n-k+1];
int top=0;
for(int i=0;i<n-k+1;i++){
max=nums[i];
for(int j=i+1;j<i+k;j++){
max=Math.max(max,nums[j]);
}
result[top++]=max;
}
return result;
}
}
class Solution { //时间复杂度O(n),AC
public int[] maxSlidingWindow(int[] nums, int k) {
int n=nums.length;
int left[]=new int [n];//此位置到该块第一位的最大数
int right[]=new int [n];//此位置到该块最后一位的最大数
for(int i=0;i<n;i++){
if(i%k==0){//当其为块的第一位
left[i]=nums[i];
}else{
left[i]=Math.max(left[i-1],nums[i]);
}
if((n-i-1)%k==k-1||(n-i-1)==n-1){//当其为块的最后一位或者为数组的最后一位
right[n-i-1]=nums[n-i-1];
}else{
right[n-i-1]=Math.max(right[n-i],nums[n-i-1]);
}
}
int result[]=new int [n-k+1];
for(int i=0;i<n-k+1;i++){
result[i]=Math.max(right[i],left[i+k-1]);
}
return result;
}
}