LeetCode 有效三角形的个数

原创 2018年04月17日 19:06:54

背景:这个题目解法是利用排序降低复杂度的一个例子

给定一个包含非负整数的数组,你的任务是统计其中可以组成三角形三条边的三元组个数。

示例 1:

输入: [2,2,3,4]
输出: 3
解释:
有效的组合是: 
2,3,4 (使用第一个 2)
2,3,4 (使用第二个 2)
2,2,3

注意:

  1. 数组长度不超过1000。
  2. 数组里整数的范围为 [0, 1000]。

分析:

 三角形的条件:第三边大于两边差,小于两边之和 因此,对于这个问题,需要判断可能的搭配:

c > abs(a - b)
c < a + b

那么,穷举每种可能来判断就可以啦:代码如下

class Solution:
    def triangleNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        rnum = 0
        bvld = False
        p1 = 0
        p2 = 1
        p3 = 2
        le = len(nums)
        for p1 in range(le - 2):
            for p2 in range(p1 + 1, le - 1):
                ma = nums[p1] + nums[p2]
                mi = abs(nums[p1] - nums[p2])
                for p3 in range(p2 + 1, le):
                    if nums[p3] in range(mi + 1, ma):
                        rnum += 1
                        #print(mi, ma)
                        #print(p1, p2, p3)
        return rnum

算法复杂度o(n^3),时间超限

转变思路:能否不遍历每种可能性?可以,只要数组有序,那么找到边界就可以找到所有满足的组合!因此,思路如下:

1. 排序
2. 找边界

第一版:外层做2层循环,第三层变遍历为找边界,两边同时开始找,找到以后,左右边界可以做差得到满足结果的组合数量,累加得到结果即可:如下:

class Solution:
    def triangleNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        rnum = 0
        nums.sort()
        p1 = 0
        p2 = 1
        p3 = 2
        le = len(nums)
        for p1 in range(le - 2):
            for p2 in range(p1 + 1, le - 1):
                bvld = False
                ma = nums[p1] + nums[p2]
                mi = abs(nums[p1] - nums[p2])
                pl = p2 + 1
                pr = le - 1
                while pr >= pl:
                    if nums[pr] < ma:
                        bvld = True
                        break
                    if nums[pr] >= ma:
                        pr -= 1                    
                if bvld:
                    rnum += pr - pl + 1
        return rnum

速度提升的比较明显,第一个算法只能跑一半的用例,这个算法能跑到最后几个,但是还是时间超限。接下来的任务还是降低复杂度,能不能把外层的2层循环拆掉一层呢?

即:每次先拿到第三条边,然后找前两条边的范围!这样复杂度可以下降到0(n^2)!代码如下(C++)

class Solution {
public:
    int triangleNumber(vector<int>& nums) {
        int count = 0, size = nums.size();
        sort(nums.begin(), nums.end());
        for (int i = size - 1; i >= 2; i--) {    // 先拿到第3条边
            int left = 0, right = i - 1;    // 前2条边
            while(left < right) {
                if (nums[left] + nums[right] > nums[i]) {
                    count += (right - left);    // 找到区间以后,就更新第2条边,构建新组合,并记录上个组合的总数
                    right--;
                }
                else {
                    left++;    // 调整第1条边
                }
            }
        }
        return count;
    }
};

解析如代码注释,这个算法更好的利用了排序的结果

总结:

算法中的数组如果有明显的大小比较判定环节,如果不排序的算法复杂度已经到了0(n^2)这个级别,那么先用O(nlgn)排序再设计往往能降低复杂度。如果复杂度到不了这个级别,排序似乎没有太大必要,毕竟排序的开销也不能忽视。

Example: How to Packetize a TCP Stream

The following example code is designed to replace the recv() call. recv_packet() differs by returnin...
  • ajiva
  • ajiva
  • 2002-11-08 09:35:00
  • 882

Leetcode611. 计算数组中可构成三角形的个数

指针夹逼
  • obrcnh
  • obrcnh
  • 2017-11-25 20:08:20
  • 123

Leetcode:Triangle 数字三角形

Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent n...
  • u012118523
  • u012118523
  • 2014-04-14 17:18:45
  • 642

查找数组中是否存在任意三个数可组成三角形的算法

分治法: 先把数组一a[i]为界,分成两部分,左边比a[i]小,右边比a[i]大。 接下来问题就变成了两个子问题,左右两个子数组,再加上一下这三种情况: 1:左面数组去一个数、右面数组取一个数,a[i...
  • u011523796
  • u011523796
  • 2013-07-27 13:52:21
  • 1966

Leetcode 120 Triangle 三角形最小路径和

给出一个三角形(数据数组),找出从上往下的最小路径和。每一步只能移动到下一行中的相邻结点上。空间复杂度要求O(n)。...
  • smile_watermelon
  • smile_watermelon
  • 2015-07-03 14:29:16
  • 823

leetcode 括号组合题目 20 是否是有效括号 32 最大有效括号 301 去掉无效括号

20. Valid Parentheses 有效括号 Given a string containing just the characters '(', ')', '{', '}', '[' ...
  • m0_37693059
  • m0_37693059
  • 2017-08-04 18:26:27
  • 435

Triangle 三角形求最小路径和 @leetcode

动态规划的题目,f[i][j] 表示某hk public class Solution { public int minimumTotal(ArrayList> triangle) { ...
  • imabluefish
  • imabluefish
  • 2014-08-18 10:06:28
  • 737

LeetCode 36 Valid Sudoku(有效数独)

翻译数独板被部分填充,空格部分用'.'来填充。一个部分填充的数组是否有效只需要看其填充的部分即可。原文代码这道题写了一会,错了……因为输入太懒搞了,就直接看了别人写的……class Solution ...
  • NoMasp
  • NoMasp
  • 2015-11-30 20:58:35
  • 3610

LeetCode 120. Triangle(三角形)

原题网址:https://leetcode.com/problems/triangle/ Given a triangle, find the minimum path sum from top ...
  • jmspan
  • jmspan
  • 2016-05-24 00:20:03
  • 370

leetcode--36. 有效的数独

题目:36. 有效的数独链接:https://leetcode-cn.com/problems/valid-sudoku/description/给定一个数独残局,判断是否合法(不一定要有解)。逐行逐...
  • Hilavergil
  • Hilavergil
  • 2018-04-12 15:05:00
  • 26
收藏助手
不良信息举报
您举报文章:LeetCode 有效三角形的个数
举报原因:
原因补充:

(最多只允许输入30个字)