這道以前認爲的難題,今天花了十分鐘不到就KO了,紀念下。。。
一、題目概要
給定一個數組 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
二、題目理解
這是一道看起來很簡單的題,自己寫個比較k個數中最大值的函數,依次遍歷就能解決。爲什麼能這樣解決呢,因爲暴力法是萬能的。
拋開上述那種暴力美學不談,我第一個念頭就是動態規劃。爲什麼我會有這樣的思維遷移,因爲我認識到題解是由一步步子解構成的:要求k個,那肯定要從1個開始,這就和最長迴文串算法很相像了。
三、解題思路
既然使用動態規劃,那肯定要拆分子問題。(覺得很簡單的時候,就不想過多的去闡述思路,只有比較難的時候,纔會覺得理清思路更有用些)
中間比較關鍵的一點就是狀態轉移方程:
如果要求從數組begin到end窗口爲k的最大值,可以用從數組begin到end-1的值和nums[end]比較:
dp[j][end]=(dp[j][end - 1] < nums[end])?nums[end]:dp[j][end - 1]
詳細代碼如下:
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k)
{
vector<int> result = {};
if (nums.size() <= 0)
return {};
//dp[i][i]表示數組下表從i到i的最大值
vector<vector<int>> dp(nums.size(), vector<int>(nums.size()));
//先單獨處理只有一個數字的情況
for (int i = 0; i < nums.size(); i++)
dp[i][i] = nums[i];
//將滑動窗口個數作爲增大的條件
for (int i = 2; i <= k; i++)
{
for (int j = 0; j < nums.size(); j++)
{
int end = j + i - 1;
if (end >= nums.size())
break;
if (dp[j][end - 1] < nums[end])
dp[j][end] = nums[end];
else
dp[j][end] = dp[j][end - 1];
}
}
for (int i = 0; i <= nums.size() - k; i++)
result.push_back(dp[i][i + k - 1]);
return result;
}
};