Given an array consists of non-negative integers, your task is to count the number of triplets chosen from the array that can make triangles if we take them as side lengths of a triangle.
Example 1:
Input: [2,2,3,4] Output: 3 Explanation: Valid combinations are: 2,3,4 (using the first 2) 2,3,4 (using the second 2) 2,2,3
Note:
- The length of the given array won't exceed 1000.
- The integers in the given array are in the range of [0, 1000].
這道題給了我們一堆數字,問我們能組成多少個正確的三角形,我們初中就知道三角形的性質,任意兩條邊之和要大於第三邊。那么問題其實就變成了找出所有這樣的三個數字,使得任意兩個數字之和都大於第三個數字。那么可以轉變一下,三個數字中如果較小的兩個數字之和大於第三個數字,那么任意兩個數字之和都大於第三個數字,這很好證明,因為第三個數字是最大的,所以它加上任意一個數肯定大於另一個數。這樣,我們就先要給數組排序,博主最先嘗試了暴力破解法,結果TLE了(不要吐槽博主哈,博主就是喜歡霸王硬上弓~),后來優化的方法是先確定前兩個數,將這兩個數之和sum作為目標值,然后用二分查找法來快速確定第一個小於目標值的數,這種情況屬於博主之前的博客LeetCode Binary Search Summary 二分搜索法小結中總結的第二類的變形,我們找到這個臨界值,那么這之前一直到j的位置之間的數都滿足題意,直接加起來即可,參見代碼如下:
解法一:
class Solution { public: int triangleNumber(vector<int>& nums) { int res = 0, n = nums.size(); sort(nums.begin(), nums.end()); for (int i = 0; i < n; ++i) { for (int j = i + 1; j < n; ++j) { int sum = nums[i] + nums[j], left = j + 1, right = n; while (left < right) { int mid = left + (right - left) / 2; if (nums[mid] < sum) left = mid + 1; else right = mid; } res += right - 1 - j; } } return res; } };
其實還有更進一步優化的方法,用的是博主之前那篇3Sum Smaller里面的解法二,明明博主以前都總結過,換個題目情景就又沒想到,看來博主的舉一反三能力還是有所欠缺啊。沒辦法,只能繼續刻意練習了。這種方法能將時間復雜度優化到O(n2), 感覺很叼了。思路是排序之后,從數字末尾開始往前遍歷,將left指向首數字,將right之前遍歷到的數字的前面一個數字,然后如果left小於right就進行循環,循環里面判斷如果left指向的數加上right指向的數大於當前的數字的話,那么right到left之間的數字都可以組成三角形,這是為啥呢,相當於此時確定了i和right的位置,可以將left向右移到right的位置,中間經過的數都大於left指向的數,所以都能組成三角形,就說這思路叼不叼!加完之后,right自減一,即向左移動一位。如果left和right指向的數字之和不大於nums[i],那么left自增1,即向右移動一位,參見代碼如下:
解法二:
class Solution { public: int triangleNumber(vector<int>& nums) { int res = 0, n = nums.size(); sort(nums.begin(), nums.end()); for (int i = n - 1; i >= 2; --i) { int left = 0, right = i - 1; while (left < right) { if (nums[left] + nums[right] > nums[i]) { res += right - left; --right; } else { ++left; } } } return res; } };
類似題目:
參考資料:
https://discuss.leetcode.com/topic/92099/java-o-n-2-time-o-1-space