题目
给定一个数组 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
提示:
1 <= nums.length <= 10^5
-10^4 <= nums[i] <= 10^4
1 <= k <= nums.length
1.首先找出数组中最前面k个元素的最大值,放在返回数组ret[0]
中。
2.之后每往后滑动时,先判断滑走的元素是否为最大值,
2.1若最大值仍然在窗口中,判断最大值和滑入窗口的元素的值,取较大者。
2.2 若最大值滑走,则在新窗口元素中重新找最大值。
int Max(int* num,int left,int right)
即数组名,开始的下标,结束的下标。int* returnSize
1.首先要判断传入参数的合法性!如果传入数组为NULL
则类似nums[i]
的操作都是非法的,所以一定要先判断if(numsSize==0)
再进一步行动!
2.其次,确定此数组的大小int* returnSize
,由窗口滑动的特性我们可以发现*returnSize=numsSize+1-k;
3.在窗口滑动时,要注意最后一个元素为特殊边界,在下面代码中,我加入了这一段来防止溢出
if(i+k==numsSize)
break;
下面是完整代码:
int Max(int* num,int left,int right)
{
int max=num[left];
for(int i=left;i<=right;i++)
{
if(max<num[i])
max=num[i];
}
return max;
}
int* maxSlidingWindow(int* nums, int numsSize, int k, int* returnSize)
{
if(numsSize==0)
{
*returnSize=0;
return NULL;
}
int *ret;
ret = (int *)malloc(sizeof(int)*(numsSize-k+1));
int i,j;
ret[0] = Max(nums,0,k-1);
int max;
max=ret[0];
for(i=0;i<(numsSize+1-k);i++)
{
ret[i] = max;
if(i+k==numsSize)
break;
if(ret[i]>nums[i])//最大值没有出队
{
if(ret[i]<nums[i+k])//且新入队元素比最大值大
max=nums[i+k];
}
/*
上面两个嵌套的if循环不可以改成
if(ret[i]>nums[i]&&(ret[i]
else
{
max = Max(nums,i+1,i+k);
}
}
*returnSize=numsSize+1-k;
return ret;
}
最后附上自己用于测试的main函数
int main()
{
int nums[]={-2,5,8,-9,3,0,45,-90};
int a=1;
int *arr=maxSlidingWindow(nums, 8, 3,&a);
//printf("a=%d\n",a);
for(int i=0;i<a;i++)
{
printf("%d\n",arr[i]);
}
return 0;
}