python3__leecode/0611. 有效三角形的个数

一、刷题内容

原题链接

https://leetcode-cn.com/problems/valid-triangle-number/

内容描述

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

示例 1:

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

注意:
数组长度不超过1000。
数组里整数的范围为 [0, 1000]。

二、解题方法

1.方法一:排序 + 二分查找

对于正整数 a, b, ca,b,c,它们可以作为三角形的三条边,当且仅当:

a+b>c
a+c>b
b+c>a

均成立。如果我们将三条边进行升序排序,使它们满足 a≤b≤c,那么 a + c > b 和 b + c > a 使一定成立的,我们只需要保证 a + b > c。

注意到题目描述中 nums 包含的元素为非负整数,即除了正整数以外,nums 还会包含 0。但如果我们将 nums 进行升序排序,那么在枚举 a 和 b 时出现了 0,那么 nums[i] 一定为 0。此时,边 c 需要满足 c<nums[i]+nums[j]=nums[j],而下标在 [j + 1, n - 1][j+1,n−1] 范围内的元素一定都是大于等于 nums[j] 的,因此二分查找会失败。若二分查找失败,我们可以令 k = j,此时对应的范围长度 k - j = 0,我们也就保证了答案的正确性。

class Solution:
    def triangleNumber(self, nums: List[int]) -> int:
        n = len(nums)
        nums.sort()
        ans = 0
        for i in range(n):
            for j in range(i + 1, n):
                left, right, k = j + 1, n - 1, j
                while left <= right:
                    mid = (left + right) // 2
                    if nums[mid] < nums[i] + nums[j]:
                        k = mid
                        left = mid + 1
                    else:
                        right = mid - 1
                ans += k - j
        return ans

时间复杂度:O(n^2 log n),其中 n 是数组 nums 的长度。我们需要 O(n^2 log n) 的时间对数组 nums 进行排序,随后需要 O(n^2 log n)的时间使用二重循环枚举 a, b 的下标以及使用二分查找得到 c 的下标范围。

空间复杂度:O(logn),即为排序需要的栈空间。

2.方法二:排序 + 双指针

class Solution:
    def triangleNumber(self, nums: List[int]) -> int:
        n = len(nums)
        nums.sort()
        ans = 0
        for i in range(n):
            k = i
            for j in range(i + 1, n):
                while k + 1 < n and nums[k + 1] < nums[i] + nums[j]:
                    k += 1
                ans += max(k - j, 0)
        return ans

时间复杂度:O(n^2),其中 n 是数组 nums 的长度。我们需要 O(n logn) 的时间对数组 nums 进行排序,随后需要 O(n^2)的时间使用一重循环枚举 a 的下标以及使用双指针维护 b, c 的下标。

空间复杂度:O(logn),即为排序需要的栈空间。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

百里 Jess

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值