题目

image.png

思路

  • 首先排序,通过有序性才能确定二分性
  • 确定第一个边,最小的边,nums[i],然后j = i + 1,选择第二条边nums[j],然后逐个遍历数组,这样就不会出现的重复的现象。
  • 确定了前两条边之后,问题在于如何找第三条边,第三条边在[j, n - 1]区间当中,n为数组整体长度。可以通过二分找到符合小于两边之和条件的最后一条边,相当于符合条件区间的右端点,然后通过这个位置就可以得到第三条边的数量。
  • 需要注意的是,如果不存在符合条件的区间,边缘的情况需要独立处理。二分往往会遇到这种问题。

    代码

    1. class Solution {
    2. public:
    3. int triangleNumber(vector<int>& nums) {
    4. int n = nums.size();
    5. if (n <= 2) {
    6. return 0;
    7. }
    8. sort(nums.begin(), nums.end());
    9. int cnt = 0;
    10. for (int i = 0; i < n; ++i) {
    11. for (int j = i + 1; j < n; ++j) {
    12. int left = j + 1, right = n - 1;
    13. while (left < right) {
    14. int mid = (left + right + 1) / 2;
    15. // 取符合区间的右端点
    16. if (nums[mid] < nums[i] + nums[j]) {
    17. left = mid;
    18. } else {
    19. right = mid - 1;
    20. }
    21. }
    22. cnt += (right - j);
    23. // 如果右端点恰好卡在左边界上
    24. if (right == j + 1) {
    25. cnt -= (nums[right] >= nums[i] + nums[j] ? 1 : 0);
    26. }
    27. }
    28. }
    29. return cnt;
    30. }
    31. };