题解 | #最大四边形面积#
最大四边形面积
http://www.nowcoder.com/practice/0eaf4653f1d243d4a46b3d5d60a7362e
题意整理:
在题目给出的数组中,选择四个数,将其组成一个四边形,求解数组中的数能够组成的四边形中的最大面积。
四边形的不稳定结果,其面积可以变化,所以需要分析四条边能够组成的最大面积
首先明确,当存在一条边的长度大于等于其他三条边的长度之和时,这四条边无法组成四边形,面积为0.
再则,可以得出一个结论,当四条边组成的四边形令其四个点在四边形的外界圆上时,面积最大,下面给出简单证明。
对四边形ABCD,其边长分别为a,b,c,d,记面积为S
(1)
对于对角线AC,由余弦定理有
消去AC,得到
(2)
由得到
既
容易看出,想令S最大,必须令,也即
,这就证明了S最大时四点都在其外接圆上。接下来代入
对S进行简化,得到
运用一系列平方差公式最后可以得到
令,有
方法一:
核心思想:
由上述公式,枚举四条边进行计算即可。
核心代码:
class Solution {
public:
double help(int d1, int d2, int d3, int d4) {
int sum = d1 + d2 + d3 + d4;
//不满足条件既存在边d大于等于其他三边之和
//既d >= (sum - d)
//既为2 * d >= sum
if(2 * d1 >= sum || 2 * d2 >= sum || 2 * d3 >= sum || 2 * d4 >= sum) {
return 0.0;
}
double dsum = sum / 2.0;
//根据公式返回结果
return sqrt((dsum - d1) * (dsum - d2) * (dsum - d3) * (dsum - d4));
}
double solve(vector<int>& a) {
int n = a.size();
double ans = 0.0;
//枚举四条边
for(int i = 0; i < n; ++i) {
for(int j = i + 1; j < n; ++j) {
for(int k = j + 1; k < n; ++k) {
for(int m = k + 1; m < n; ++m) {
ans = max(ans, help(a[i], a[j], a[k], a[m]));
}
}
}
}
return ans;
}
};复杂度分析:
时间复杂度:。采用的四层循环。更严谨的说,复杂度是
,既从n个数字中取出4个,但实际上
,既从时间复杂度的角度来说,仍然是
空间复杂度:,只使用了常数个变量
方法二:
核心思想:
方法一是对所有的数对进行枚举后判断,实际上可以有很大的优化空间,因为题目要求的只是最大面积。
首先对数组排序,对有序的数组,从大到小枚举最大的那条边,并判断在其之前的三条边能否与其构成四边形,如果不能则枚举下一个最大边。这样不会丢失答案,因为对有序数组a,对边i,,则对其之前的所有的边中,都不会存在能够与其组成四边形的数。
核心代码:
class Solution {
public:
double solve(vector<int>& a) {
int n = a.size();
sort(a.begin(), a.end(), greater<int>());//从大到小排序
for(int i = 0; i < n - 3; ++i) {
if(a[i] < a[i + 1] + a[i + 2] + a[i + 3]) {
double sum = (a[i] + a[i + 1] + a[i + 2] + a[i + 3]) / 2.0;
return sqrt((sum - a[i]) * (sum - a[i + 1]) * (sum - a[i + 2]) * (sum - a[i + 3]));
}
}
return 0.0;
}
};复杂度分析:
时间复杂度:,排序消耗
,枚举消耗
空间复杂度:,只使用常数个变量
查看20道真题和解析
