题解 | #最大四边形面积#
最大四边形面积
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; } };
复杂度分析:
时间复杂度:,排序消耗,枚举消耗
空间复杂度:,只使用常数个变量