1. 題目來源
2. 題目說明
3. 題目解析
方法一:暴力投機+常規解法
很暴力的一個暴力解法,加上一個特判就過了,若數組的最大項減去最小項還小於等於 limit
的話,說明應該返回整個數組長度。這個可有效避免重複項…但這個屬實有點投機了,不推薦,但是真香 😃。
參見代碼如下:
// 執行用時 :124 ms, 在所有 C++ 提交中擊敗了100.00%的用戶
// 內存消耗 :30.3 MB, 在所有 C++ 提交中擊敗了100.00%的用戶
class Solution {
public:
int longestSubarray(vector<int>& nums, int limit) {
int res = 0, c = nums[0], d = nums[0];
for (auto e : nums) c = max(c, e), d = min(d, e);
if (abs(c - d) <= limit) return nums.size();
for (int i = 0; i < nums.size(); ++i) {
int mx = nums[i], mi = nums[i], j = i;
for (j; j < nums.size(); ++j) {
mx = max(mx, nums[j]);
mi = min(mi, nums[j]);
if (abs(mx - mi) > limit) break;
}
res = max(res, j - i);
}
return res;
}
};
方法二:優先隊列+雙指針+巧妙解法
這道題符合雙指針思想,即固定 left
使 right
在條件下不斷向右移動,移動到 n
或者未在條件內就跳出循環。採用兩個優先隊列來求出區間的最大、最小值。這個的時間複雜度爲 ,並且採用優先隊列求最大值就正常數據輸入即可,求最小值時可以採用給數據乘負號的形式輸入,輸出時再乘負號即可。在此 make_pair
是一個函數,無法使用 typedef
,就使用簡單的宏替換即可,相當於字符串替換。但還是儘量少用宏定義吧。
不過這執行用時真的離譜了點…確實最後一個 case
很頂啊,不過這個解法確實能有效通過最後一個用例。
參見代碼如下:
// 執行用時 :468 ms, 在所有 C++ 提交中擊敗了100.00%的用戶
// 內存消耗 :34.7 MB, 在所有 C++ 提交中擊敗了100.00%的用戶
typedef pair<int, int> PII;
#define MP(x, y) make_pair(x, y)
class Solution {
public:
int longestSubarray(vector<int>& nums, int limit) {
int ans = 0, n = nums.size();
priority_queue<PII> mxq, miq;
for (int i = 0, r = 0; i < n; ++i) {
while (!mxq.empty() and mxq.top().second < i) mxq.pop();
while (!miq.empty() and miq.top().second < i) miq.pop();
int mx = 0, mi = 1e9 + 1;
if (!mxq.empty()) mx = mxq.top().first;
if (!mxq.empty()) mi = -miq.top().first;
while (r < n and max(mx, nums[r]) - min(mi, nums[r]) <= limit) {
mxq.push(MP(nums[r], r));
miq.push(MP(-nums[r], r));
mx = max(mx, nums[r]);
mi = min(mi, nums[r]);
++r;
}
ans = max(ans, r - i);
}
return ans;
}
};