動態規劃專欄(三):滑動窗口最大值

這道以前認爲的難題,今天花了十分鐘不到就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;
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章