LC-239 移动窗口的最大值
目标:
给出一个数组和一个k大小的窗口,窗口从头开始,每次移动一个元素,直到到达数组尾,给出每次窗口的最大值。思考如何在线性时间内完成。
主要思路:
一开始,我实现的是,遍历窗口,移动,每次都找出该窗口的最大值,然后输出。这种方法的时间复杂度为O(nk),理论上k是一个定值,所以可以看作是O(n),但实际上,k从1到n,所以最差情况下,时间复杂度是O(n2),其实并不符合。
我在Leetcode上查看讨论,发现很多方法其实都是O(nk)的,但有一个是真的O(n)的算法:
他首先将数组按k个分组,然后巧妙地用2个数组,分别为left_max,right_max来记录每个位置在该小组的左边最大值与右边最大值。然后,遍历一次,当前窗口的最大值,就是该窗口起始点位置的右边最大值及终点位置的左边最大值。
代码:
1 class Solution { 2 public: 3 vector<int> maxSlidingWindow(vector<int>& nums, int k) { 4 int len = nums.size(); 5 if (len == 0) return nums; 6 7 int *left_max = new int[len]; 8 int *right_max = new int[len]; 9 10 left_max[0] = nums[0]; 11 right_max[len - 1] = nums[len - 1]; 12 13 for (int i = 1; i < len; i++) { 14 left_max[i] = (i % k == 0) ? nums[i] : max(left_max[i - 1], nums[i]); 15 16 int j = len - i - 1; 17 right_max[j] = (j % k == 0) ? nums[j] : max(right_max[j + 1], nums[j]); 18 } 19 20 vector<int> result; 21 for (int i = 0; i < len - k + 1; i++) { 22 result.push_back(max(right_max[i], left_max[i + k - 1])); 23 } 24 25 return result; 26 } 27 };