2971. Find Polygon with the Largest Perimeter - Explanation
Description
Choose at least three entries of nums as side lengths of a polygon. Such a polygon exists exactly when its longest side is strictly shorter than the sum of all other chosen sides. Return the largest possible sum of chosen side lengths, or -1 if no polygon can be formed.
Example 1:
Input: nums = [2,3,4]
Output: 9Explanation: Use all three sides. The longest side, 4, is smaller than 2 + 3, so the perimeter is 2 + 3 + 4 = 9.
Example 2:
Input: nums = [1,2,3]
Output: -1Explanation: The longest side equals 1 + 2, but the inequality must be strict. With only three available entries, no polygon is possible.
Example 3:
Input: nums = [3,3,3,20]
Output: 9Explanation: The side of length 20 exceeds the sum of the other sides, so it cannot be used. The three sides of length 3 form a polygon with perimeter 9.
Constraints:
3 <= nums.length <= 1000001 <= nums[i] <= 1000000000
Topics
Prerequisites
Before attempting this problem, you should be comfortable with:
- Sorting - Arranging elements to efficiently identify the largest side and compare sums
- Prefix Sum - Maintaining running totals to quickly compute the sum of smaller sides
- Polygon Inequality - Understanding that the longest side must be strictly less than the sum of all other sides
1. Brute Force
Intuition
A valid polygon requires that the longest side be strictly smaller than the sum of all other sides. We can try each element as the largest side and check if this condition holds. For each candidate, we sum all elements that are less than or equal to it (excluding itself) and verify whether that sum exceeds the candidate. If it does, we have a valid polygon and can compute its perimeter.
Algorithm
- Initialize
res = -1to track the maximum perimeter found. - For each element
nums[i], treat it as the potential largest side. - Sum all other elements
nums[j]wherenums[j] <= nums[i]. - If the sum of smaller sides exceeds
nums[i], updatereswith the total perimeter. - Return
resafter checking all possibilities.
class Solution:
def largestPerimeter(self, nums: List[int]) -> int:
n = len(nums)
res = -1
for i, large in enumerate(nums):
cur = 0
for j, side in enumerate(nums):
if i != j and side <= large:
cur += side
if cur > large:
res = max(res, cur + large)
return resTime & Space Complexity
- Time complexity:
- Space complexity: extra space.
2. Sorting
Intuition
If we sort the array, we can efficiently check the polygon condition. After sorting, as we iterate through each element, all previous elements are smaller or equal. The key insight is that if the running sum of all previous elements exceeds the current element, we have a valid polygon. Since we want the largest perimeter, we keep updating our answer as we find valid configurations, and the last valid one will be the largest.
Algorithm
- Sort the array in ascending order.
- Initialize
res = -1andtotal = 0for the running sum. - Iterate through each number:
- If
total > num, we have a valid polygon. Updateres = total + num. - Add
numtototal.
- If
- Return
res.
Time & Space Complexity
- Time complexity:
- Space complexity: or depending on the sorting algorithm.
3. Max Heap
Intuition
Instead of sorting, we can use a max heap to process elements from largest to smallest. We start with the total sum and repeatedly extract the maximum element. If the remaining sum (after removing the max) is greater than the max element, we found the largest valid polygon. Otherwise, we subtract that element from our total and try the next largest. This approach can be faster in practice since we often find the answer before processing all elements.
Algorithm
- Build a max heap from all elements and compute the total sum.
- While the heap has more than
2elements:- Extract the largest element.
- Subtract it from the total.
- If
largest < total, returntotal + largestas the perimeter.
- If no valid polygon is found, return
-1.
class Solution:
def largestPerimeter(self, nums: List[int]) -> int:
nums = [-num for num in nums]
heapq.heapify(nums)
total = -sum(nums)
while len(nums) > 2:
largest = -heapq.heappop(nums)
total -= largest
if largest < total:
return total + largest
return -1Time & Space Complexity
- Time complexity:
- in Python, C++, JS.
- in Java.
- Space complexity:
Common Pitfalls
Using Greater-Than-or-Equal Instead of Strictly Greater
The polygon inequality requires that the longest side be strictly less than the sum of all other sides (equivalently, the sum of other sides must be strictly greater than the longest side). Using >= instead of > in the comparison will incorrectly accept degenerate cases where the sides form a straight line, not a valid polygon.
Integer Overflow with Large Sums
The array can contain up to 10^5 elements, each up to 10^9. The sum of all elements can exceed the 32-bit integer range. Use 64-bit integers (long in Java, long long in C++) for the running total and result to prevent overflow and incorrect comparisons.
Forgetting That Polygons Need At Least 3 Sides
A valid polygon requires at least 3 sides. When iterating through the sorted array, you cannot form a valid polygon until you have accumulated at least 2 previous elements. Starting the validity check too early (e.g., at index 0 or 1) can lead to incorrect results or accessing invalid indices.
Sign in to join the discussion