LeetCode 239. Sliding Window Maximum 題解(上)

LeetCode 239. Sliding Window Maximum 題解(上)

496. Next Greater Element I 題解

一點說明
這篇博客其實是主要寫 496. Next Greater Element I 題解 的。主要是這次做題過程中十分有意思。真的是巧合。 所以乾脆換了種寫博客的方式。 至於主標題爲什麼是LeetCode 239. Sliding Window Maximum 題解(上), 是因爲這道題要用到我們這篇博客中所用的方法。
下面是正文。

題目描述


496. Next Greater Element I

You are given two arrays (without duplicates) nums1 and nums2 where nums1’s elements are subset of nums2. Find all the next greater numbers for nums1’s elements in the corresponding places of nums2.

The Next Greater Number of a number x in nums1 is the first greater number to its right in nums2. If it does not exist, output -1 for this number.

Example 1:

Input: nums1 = [4,1,2], nums2 = [1,3,4,2].
Output: [-1,3,-1]

Example 2:

Input: nums1 = [2,4], nums2 = [1,2,3,4].
Output: [3,-1]

Note:
1. All elements in nums1 and nums2 are unique.
2. The length of both nums1 and nums2 would not exceed 1000.


題目分析

首先,這是一道Easy標籤的題目。 所以肯定不會很難AC。但是這題一旦數據設置大一些, 難度就上去了(例如把maxlen 設置爲 107 ……
好吧, 按照通常習慣, 我們先來分析一下題目。
簡單的分析就可以知道我們這題需要一個map來幫助我們優化。爲什麼呢? 我們需要找的是num1 對應在 num2中的元素的下一個 greater Element, 結合Note中,提到這些元素各不相同, 這裏顯然用一個map來建立一個映射數組下標與其儲存值之間的映射。 方向應該是: value=>index
這樣做之後, 其實剩下的就已經可以暴力求解了, 限制len<1000 也很顯然就是爲 O(n2) 算法準備的。


但是稍微想一下, 我們在暴力執行O(n2) 來找Next Greater Element 的時候, 是否進行過不必要的計算。 舉個例子:
考慮這個數列: [1,3,-1,-3,5,3,6,7](如果看了主標題中的LeetCode 239. Sliding Window Maximum這道題的話,就會發現這就是那道題中的Example)
當我們尋找index=13的Next Greater Element時,我們進行循環, 會找到 index=45, 這中間加了若干個數,我們可以得到結論: 中間這些夾的數的Next Greater Element, 也是 index=45
這個結論的證明十分簡單。 就不敘述了。對比之前暴力的做法, 顯然剩下了這些中間數的搜索時間。

接下來我們要考慮的就是如何用數據結構實現這一方法。答案是用棧。至於這怎麼想到用棧的還是偏感覺多一些, 所以也不知道怎麼寫~。~ 下一個Topic 就來說說用棧如何實現這一過程吧。

法一. 暴力求解。

這個方法唯一需要做的就是建立一個map來建立一個映射數組下標與其儲存值之間的映射。 方向是: value=>index 。之後就對每個數循環一遍就可以找到Next Greater Element 了。複雜度爲 O(n2) .
當然有一個小小改進的地方, 由於這是暴力破解, 所以沒必要對於num2的每個元素去搜索, 直接搜索我們需要的就行了,即num1的元素。 這樣的話複雜度爲 O(nk) ,其中 n=num2.size(),k=num1.size()

法二. 用棧求解。

這個方法的核心思想前面說過了。 這裏就說一下實現過程。
1. 先把第一個元素入棧。
2. 循環num2數組, 並準備依次入棧。
3. 若是當前入棧元素大於棧頂元素, 則將棧頂元素的Next Greater Element 設置爲當前入棧元素, 並將棧頂元素彈出棧。
4. 重複執行3. 直到不滿足3的條件。此時把當前元素入棧。
5. 循環一遍之後, 最後剩下在棧的那些元素的Next Greater Element 設置爲-1.

之前的過程理解的話, 這些步驟就顯然了~.~
複雜度分析:只需要掃一遍咯。。 顯然就是O(n)
注意到每次掃描一個的時候可能會出現多次出棧沒錯, 但是出棧總數固定最大爲n1 ,不會影響到複雜度的。

下面是具體代碼實現:

class Solution {
public:
    vector<int> nextGreaterElement(vector<int>& findNums, vector<int>& nums) {
        unordered_map<int, int> index;
        for (int i = 0; i < nums.size(); ++i) {
            index[nums[i]] = i;
        }
        vector<int> greaterNum(nums.size(), -1);
        stack<int> s;
        for(int i = 0; i < nums.size(); ++i) {
            while (!s.empty() && nums[s.top()] < nums[i]) {
                greaterNum[s.top()] = nums[i];
                s.pop();
            }
            s.push(i);
        }
        vector<int> ans;
        for (int i = 0; i < findNums.size(); ++i) {
            ans.push_back(greaterNum[index[findNums[i]]]);
        }
        return ans;
    }
};

其他細節

  1. 利用vector構造函數能夠初始賦值的特性, 可以初始先假設Next Greater Element 均爲 -1, 之後可以省去步驟5的工作。
  2. 能利用unordered_map儘量不用map。複雜度貌似有差異的。

這道題其實就是實現了一個這樣的功能:利用線性複雜度得到一個數組的Next Greater Element。

這題是剛好我想不到LeetCode 239. Sliding Window Maximum 這題的時候做的。 沒想到剛好能用上, 真是機緣巧合。

下一篇重點講如何將這個結論(以及方法)利用到 LeetCode 239. Sliding Window Maximum 這題上

The End.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章