最大平均值子陣列-LintCode
阿新 • • 發佈:2019-02-12
給出一個整數陣列,有正有負。找到這樣一個子陣列,他的長度大於等於 k,且平均值最大。
注意事項:
保證陣列的大小 >= k
樣例:
給出 nums = [1, 12, -5, -6, 50, 3], k = 3
返回 15.667 // (-6 + 50 + 3) / 3 = 15.667
一刷,超時。
#ifndef C617_H
#define C671_H
#include<vector>
#include<iostream>
using namespace std;
class Solution {
public:
/*
* @param nums: an array with positive and negative numbers
* @param k: an integer
* @return: the maximum average
*/
double maxAverage(vector<int> &nums, int k) {
// write your code here
int len = nums.size();
vector<double> sum(len+1, 0);
sum[0] = 0;
for (int i = 1; i <= len; ++i)
{
sum[i] = sum[i - 1] + nums[i-1];
}
int m = len;
double res = -DBL_MAX;
while (m >= k)
{
double target = -DBL_MAX;
for (int i = 0; i < len; ++i)
{
if (i + m <= len)
target = maxVal(target, sum[i + m] - sum[i]);
else
break ;
}
res = maxVal(res, target / m);
--m;
}
return res;
}
template<typename T>
T maxVal(T a, T b)
{
return a > b ? a : b;
}
};
#endif
九章答案程式碼
C++程式碼
思路:二分法
- 首先找到陣列的最大值與最小值,確定平均值的範圍;
- 不斷縮小範圍,在r-l的值足夠小的時候,得到結果
令mid=(r+l)/2,將原陣列的每個元素減去mid,如果可以找到至少k個相鄰元素的和>0,說明最終結果一定比現在的mid要大,在[l,mid]範圍內尋找,否則,在[mid,r]範圍內尋找。 - 接下來判斷是否存在有至少k個相鄰元素的>0,利用陣列sum[i]儲存sum[i]-mid到sum[i-1]-mid的和,當i>k時,用一個min_pre的變數來儲存sum[0]~sum[i-k]之間的最小值,並且每次隨著i變大不斷更新該數字。這樣sum[i]-min_pre得到的是sum[k+1]~sum[i-1],它所記錄的總和個數也就是到num[i]為止能夠找到的最大平均值子陣列的長度。
參考後代碼
#ifndef C617_H
#define C671_H
#include<vector>
#include<iostream>
using namespace std;
class Solution {
public:
/*
* @param nums: an array with positive and negative numbers
* @param k: an integer
* @return: the maximum average
*/
double maxAverage(vector<int> &nums, int k) {
// write your code here
double l = INT_MAX, r = INT_MIN;
int len = nums.size();
for (auto c : nums)
{
if (c < l)
l = c;
if (c>r)
r = c;
}
vector<double> sum(len+1, 0);
sum[0] = 0;
while (r - l >= 1e-6)
{
double mid = (l + r) / 2.0;
double min_pre = 0;
bool check = false;
for (int i = 1; i <= len; ++i)
{
sum[i] = sum[i - 1] + nums[i - 1] - mid;
if (i >= k&&sum[i] - min_pre >= 0)
{
check = true;
break;
}
if (i >= k)
min_pre = minVal(min_pre, sum[i - k + 1]);
}
if (check)
l = mid;
else
r = mid;
}
return l;
}
double minVal(double a, double b)
{
return a < b ? a : b;
}
};
#endif