三角形最大周长

转载

给定由一些正数(代表长度)组成的数组 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);
            }
        }
    }

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值