给定由一些正数(代表长度)组成的数组 A,返回由其中三个长度组成的、面积不为零的三角形的最大周长,如果不能形成任何面积不为零的三角形,返回0
题意可以翻译为:求满足三角形定义的三边之和最大值
三角形定义上要求【任意两边和大于第三边】,即【短边和大于长边】,我们只需排序,依次从高到低取三条边,满足定义返回三边和即可。
又因为,过程中每次校验都可能找到答案,所以其实完整的排序是浪费的,我们只需使用一种每次都可以把最大值筛选出来的排序算法,先筛选出来最大的两个值,之后每次得到新值都进行校验,成立即返回。
满足上述的排序算法有【选择排序】、【冒泡排序】、【堆排序】等,由于冒泡排序交换数据频繁,首先被排除掉,接着我们就分别用【选择排序】和【堆排序】来写一下吧
/**
* 方案一:先排序后筛选 [LeetCode:22ms]
*/
class Solution1 {
public int largestPerimeter(int[] A) {
Arrays.sort(A);
for (int i = A.length - 1; i >= 2; i--) {
if (A[i] < A[i - 1] + A[i - 2])
return A[i] + A[i - 1] + A[i - 2];
}
return 0;
}
}
/**
* 方案二:选择排序,提前筛选 [LeetCode:14ms]
*/
class Solution2 {
public int largestPerimeter(int[] A) {
for (int i = 0; i < A.length; i++) {
int minP = i;
for (int j = i + 1; j < A.length; j++) {
if (A[j] > A[minP]) {
minP = j;
}
}
int temp = A[i];
A[i] = A[minP];
A[minP] = temp;
if (i >= 2 && A[i - 2] < A[i - 1] + A[i])
return A[i] + A[i - 1] + A[i - 2];
}
return 0;
}
}
/**
* 方案三:大顶堆,提前筛选 [LeetCode:8ms]
*/
class Solution3 {
/**
* 大顶堆
*
* @param A
*/
public int largestPerimeter(int[] A) {
buildHeap(A);
for (int i = A.length - 1; i >= 0; i--) {
swap(A, 0, i);
adjust(A, i, 0);
if (i < A.length - 2 && A[i + 2] < A[i + 1] + A[i]) {
return A[i + 2] + A[i + 1] + A[i];
}
}
return 0;
}
/**
* 调整
*
* @param nums
* @param length
* @param x
*/
public void adjust(int[] nums, int length, int x) {
while (x <= length / 2 - 1) {
int left = nums[2 * x + 1];
int right = left - 1;
if (2 * x + 2 < length) {
right = nums[2 * x + 2];
}
int max = Math.max(left, right);
if (nums[x] >= max)
break;
if (max == left) {
int temp = nums[x];
nums[x] = left;
nums[2 * x + 1] = temp;
x = 2 * x + 1;
} else {
int temp = nums[x];
nums[x] = right;
nums[2 * x + 2] = temp;
x = 2 * x + 2;
}
}
}
/**
* 交换两个数
*
* @param nums
* @param i
* @param j
*/
public void swap(int[] nums, int i, int j) {
if (i == j)
return;
nums[i] = nums[i] ^ nums[j];
nums[j] = nums[i] ^ nums[j];
nums[i] = nums[i] ^ nums[j];
}
/**
* 建堆
*
* @param nums
*/
public void buildHeap(int[] nums) {
int length = nums.length;
for (int i = length / 2 - 1; i >= 0; i--) {
adjust(nums, nums.length, i);
}
}
}