题目
给一个大小为n
的数组T
,要求对i
从0-n
,计算出从i + 1
开始的第一个大于T[i]
的数的位置j
,并将j-i
的值记录下来。例如对于数组:[73, 74, 75, 71, 69, 72, 76, 73]
,输出数组为:1, 1, 4, 2, 1, 1, 0, 0
。
注:数组T
不为空,且最多包含30000个元素,每个元素的取值范围为[30, 100]
。
思路
因为是找i
之后的数中第一个大于T[i]
的,因此可以从后往前进行计算。
-
由于每个元素取值范围较小,所以通过下标计算每个元素出现的最小位置,之后再遍历整个值范围得到最终结果。例如对于
71, 69, 72, 76, 73
来说,从后往前:i = 4: 遍历74-100,无更大元素出现,res[4] = 0, 之后记录 mpos[73] = min(mpos[73], 4) i = 3: 遍历77-100,无更大元素出现,res[3] = 0 之后记录 mpos[76] = min(mpos[76], 3) i = 2: 遍历73-100,找到73 76两个, res[2] = min(mpos[73], mpos[76]) 之后记录 mpos[72] = min(mpos[72], 2) ...
-
不妨考虑
T = [40, 37, 35, 34, 39, 34, 35]
,从后往前遍历,到达T[4] = 39
时,由于39此时是最大的,因此其后的34, 35
其实都不需要再考虑了。进一步:i = 4, 40 37 35 34 39
34 35
i = 3, 40 37 35343934 35
i = 1, 40 3735 343934 35
i = 0, 4037 35 34 39 34 35即因为我们需要的是更靠前且更大的数,所以当遇到更大的数时即可将后面较小的数给无效化 。具体实现可以使用栈,从后往前不断将值入栈,当遇到更大的值时将栈顶所有小于其的数出栈即可。
代码
- 值当索引遍历
#define maxn 102 #define maxval 30001 class Solution { private: int min_pos[maxn]; public: vector<int> dailyTemperatures2(vector<int> &T) { const int n = T.size(); vector<int> ret(T.size(), 0); if (n <= 1) return ret; for (int i = 0; i < maxn; i++) { min_pos[i] = maxval; } min_pos[T[n - 1]] = n - 1; for (int i = n - 2; i >= 0; i--) { int tmpVal = T[i], tmpMin = maxval; for (int j = tmpVal + 1; j < maxn; j++) { tmpMin = min(tmpMin, min_pos[j]); } if (tmpMin != maxval) ret[i] = tmpMin - i; min_pos[tmpVal] = min(i, min_pos[tmpVal]); } return ret; } }
- 使用栈
class Solution { public: vector<int> dailyTemperatures(vector<int> &T) { vector<int> ret(T.size(), 0); stack<int> sta; for (int i = T.size() - 1; i >= 0; i--) { int tmpval = T[i]; while (!sta.empty() && T[sta.top()] <= T[i]) { sta.pop(); } if (!sta.empty()) ret[i] = sta.top() - i; sta.push(i); } return ret; } };