Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 13 additions & 16 deletions solution/0900-0999/0976.Largest Perimeter Triangle/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,11 @@ tags:

### 方法一:排序 + 贪心

> 三角形由三条边组成,且满足 <var>C</var> >= <var>B</var> && <var>C</var> >= <var>A</var> && <var>C</var> < <var>A</var> + <var>B</var>
我们不妨假设三角形的三条边长分别为 $a \leq b \leq c$,则三角形的面积不为零等价于 $a + b \gt c$。

贪心策略,尽可能使用长边来组成三角形
我们可以枚举最大的边长 $c$,然后从剩下的边长中选取两个最大的边长 $a$ 和 $b$,如果 $a + b \gt c$,则可以构成一个面积不为零的三角形,且该三角形的周长最大;否则继续枚举下一个最大的边长 $c$

1. 对 `nums` 排序(从大到小)。
2. 遍历 `nums`,以三个元素一组,进行条件判断,如滑动窗口一般。
3. 当找到满足条件的三个元素时直接返回即可。
4. 否则,在遍历结束时返回 0。
时间复杂度 $O(n \times \log n)$,空间复杂度 $O(\log n)$。其中 $n$ 为数组 $\textit{nums}$ 的长度。

<!-- tabs:start -->

Expand Down Expand Up @@ -108,10 +105,12 @@ class Solution {
class Solution {
public:
int largestPerimeter(vector<int>& nums) {
sort(nums.begin(), nums.end());
for (int i = nums.size() - 1; i >= 2; --i) {
ranges::sort(nums);
for (int i = nums.size() - 1; i > 1; --i) {
int c = nums[i - 1] + nums[i - 2];
if (c > nums[i]) return c + nums[i];
if (c > nums[i]) {
return c + nums[i];
}
}
return 0;
}
Expand All @@ -124,8 +123,7 @@ public:
func largestPerimeter(nums []int) int {
sort.Ints(nums)
for i := len(nums) - 1; i >= 2; i-- {
c := nums[i-1] + nums[i-2]
if c > nums[i] {
if c := nums[i-1] + nums[i-2]; c > nums[i] {
return c + nums[i]
}
}
Expand All @@ -137,11 +135,10 @@ func largestPerimeter(nums []int) int {

```ts
function largestPerimeter(nums: number[]): number {
const n = nums.length;
nums.sort((a, b) => b - a);
for (let i = 2; i < n; i++) {
const [a, b, c] = [nums[i - 2], nums[i - 1], nums[i]];
if (a < b + c) {
nums.sort((a, b) => a - b);
for (let i = nums.length - 1; i > 1; --i) {
const [a, b, c] = nums.slice(i - 2, i + 1);
if (a + b > c) {
return a + b + c;
}
}
Expand Down
30 changes: 18 additions & 12 deletions solution/0900-0999/0976.Largest Perimeter Triangle/README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ tags:
<pre>
<strong>Input:</strong> nums = [1,2,1,10]
<strong>Output:</strong> 0
<strong>Explanation:</strong>
<strong>Explanation:</strong>
You cannot use the side lengths 1, 1, and 2 to form a triangle.
You cannot use the side lengths 1, 1, and 10 to form a triangle.
You cannot use the side lengths 1, 2, and 10 to form a triangle.
Expand All @@ -56,7 +56,13 @@ As we cannot use any three side lengths to form a triangle of non-zero area, we

<!-- solution:start -->

### Solution 1
### Solution 1: Sorting + Greedy

Suppose the three sides of the triangle are $a \leq b \leq c$. The triangle has non-zero area if and only if $a + b \gt c$.

We can enumerate the largest side $c$, then select the two largest remaining sides $a$ and $b$. If $a + b \gt c$, a triangle with non-zero area can be formed, and its perimeter will be the largest possible; otherwise, continue to enumerate the next largest side $c$.

The time complexity is $O(n \log n)$, and the space complexity is $O(\log n)$, where $n$ is the length of the array $\textit{nums}$.

<!-- tabs:start -->

Expand Down Expand Up @@ -95,10 +101,12 @@ class Solution {
class Solution {
public:
int largestPerimeter(vector<int>& nums) {
sort(nums.begin(), nums.end());
for (int i = nums.size() - 1; i >= 2; --i) {
ranges::sort(nums);
for (int i = nums.size() - 1; i > 1; --i) {
int c = nums[i - 1] + nums[i - 2];
if (c > nums[i]) return c + nums[i];
if (c > nums[i]) {
return c + nums[i];
}
}
return 0;
}
Expand All @@ -111,8 +119,7 @@ public:
func largestPerimeter(nums []int) int {
sort.Ints(nums)
for i := len(nums) - 1; i >= 2; i-- {
c := nums[i-1] + nums[i-2]
if c > nums[i] {
if c := nums[i-1] + nums[i-2]; c > nums[i] {
return c + nums[i]
}
}
Expand All @@ -124,11 +131,10 @@ func largestPerimeter(nums []int) int {

```ts
function largestPerimeter(nums: number[]): number {
const n = nums.length;
nums.sort((a, b) => b - a);
for (let i = 2; i < n; i++) {
const [a, b, c] = [nums[i - 2], nums[i - 1], nums[i]];
if (a < b + c) {
nums.sort((a, b) => a - b);
for (let i = nums.length - 1; i > 1; --i) {
const [a, b, c] = nums.slice(i - 2, i + 1);
if (a + b > c) {
return a + b + c;
}
}
Expand Down
10 changes: 6 additions & 4 deletions solution/0900-0999/0976.Largest Perimeter Triangle/Solution.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
class Solution {
public:
int largestPerimeter(vector<int>& nums) {
sort(nums.begin(), nums.end());
for (int i = nums.size() - 1; i >= 2; --i) {
ranges::sort(nums);
for (int i = nums.size() - 1; i > 1; --i) {
int c = nums[i - 1] + nums[i - 2];
if (c > nums[i]) return c + nums[i];
if (c > nums[i]) {
return c + nums[i];
}
}
return 0;
}
};
};
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
func largestPerimeter(nums []int) int {
sort.Ints(nums)
for i := len(nums) - 1; i >= 2; i-- {
c := nums[i-1] + nums[i-2]
if c > nums[i] {
if c := nums[i-1] + nums[i-2]; c > nums[i] {
return c + nums[i]
}
}
return 0
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
function largestPerimeter(nums: number[]): number {
const n = nums.length;
nums.sort((a, b) => b - a);
for (let i = 2; i < n; i++) {
const [a, b, c] = [nums[i - 2], nums[i - 1], nums[i]];
if (a < b + c) {
nums.sort((a, b) => a - b);
for (let i = nums.length - 1; i > 1; --i) {
const [a, b, c] = nums.slice(i - 2, i + 1);
if (a + b > c) {
return a + b + c;
}
}
Expand Down