题目
给定由一些正数(代表长度)组成的数组 nums ,返回 由其中三个长度组成的、面积不为零的三角形的最大周长 。如果不能形成任何面积不为零的三角形,返回 0。
示例 1:
输入:nums = [2,1,2] 输出:5 解释:你可以用三个边长组成一个三角形:1 2 2。
示例 2:
输入:nums = [1,2,1,10] 输出:0 解释: 你不能用边长 1,1,2 来组成三角形。 不能用边长 1,1,10 来构成三角形。 不能用边长 1、2 和 10 来构成三角形。 因为我们不能用任何三条边长来构成一个非零面积的三角形,所以我们返回 0。
提示:
3 <= nums.length <= 10^41 <= nums[i] <= 10^6
解题思路
第一步:排序 将整个数组
nums按升序排序。这样做的好处有两个:方便我们应用上面提到的简化版三角不等式。
让最大的元素都集中在数组的末尾,便于我们从大到小进行选择。
第二步:贪心遍历 我们从数组的末尾开始向前遍历,寻找第一个能构成三角形的组合。
设当前遍历到的最大边的索引为
i(从nums.length - 1开始)。我们将
nums[i]作为最长边c。然后,我们选择与它相邻的两个较小的边,即
nums[i-1]作为边b,nums[i-2]作为边a。检查它们是否满足条件:
nums[i-2] + nums[i-1] > nums[i]。
第三步:判断与返回
如果满足
nums[i-2] + nums[i-1] > nums[i]:我们已经找到了一个有效的三角形。
因为我们是从大到小遍历的,并且每次都选择当前最大的三个连续元素,所以这个三角形的周长
nums[i-2] + nums[i-1] + nums[i]一定是所有可能组合中最大的。直接返回这个周长即可。
如果不满足
nums[i-2] + nums[i-1] <= nums[i]:这说明
nums[i]这条边相对于其他两条边来说“太长了”。由于
nums[i-1]和nums[i-2]已经是除nums[i]之外最大的两条边了,如果连它们俩加起来都无法大于nums[i],那么数组中任何其他更小的两条边(例如nums[i-3],nums[i-4]等)的和也必然小于nums[i]。因此,
nums[i]这条边不可能与数组中任何其他两条边构成三角形。我们可以放心地“抛弃”nums[i],继续向前考察下一组,即将nums[i-1]作为最长边,继续检查nums[i-3] + nums[i-2] > nums[i-1]。
第四步:处理边界情况
- 如果循环结束(即
i遍历到小于 2)都没有找到满足条件的组合,说明数组中任意三个数都无法构成三角形。此时,按题目要求返回0。
- 如果循环结束(即
具体代码
class Solution {
public:
int largestPerimeter(vector<int>& nums) {
sort(nums.begin(), nums.end());
int n = nums.size();
for(int i = n - 1; i >= 2; --i)
{
if(nums[i - 2] + nums[i - 1] > nums[i])
{
return nums[i] + nums[i - 1] + nums[i - 2];
}
}
return 0;
}
};