今日为大家分享一道力扣611有效三角形的个数!本文将会为大家为大家讲解题目,然后算法思路,最后再进行代码的实现!希望看完本文能对读者有一定的收获!
一、题目描述
通过题目的描述可以看出,意思是给定一个数组,然后观察数组中能元素组成三角形的个数!
题目上面那个例题可以看出,不同位置相同的数组也算不同的情况!
二、算法解析+代码!
相信不少小伙伴一看到本题,想到的大多都是暴力法!即:依次遍历,然后统计每次的数据是否能组成三角形!这样的解法是没毛病,但是放在力扣里面,其时间复杂度是很大可能是通不过的!下面我就来为大家写一下这种暴力枚举的算法代码!(在进行暴力枚举之前,可以将数组排成有序的!方便我们后边的暴力枚举分情况!)
1.暴力枚举
class Solution {
public:
//首先先将数组中的元素进行排序,可以有效的减少时间的复杂度!
//然后根据单调性,利用双指针来判断能否组成三角形!
int triangleNumber(vector<int>& nums)
{
sort(nums.begin(),nums.end());
//暴力枚举!
int count=0;
int len=nums.size();
for(int i=0;i<len-2;i++)
{
for(int j=i+1;j<len-1;j++)
{
for(int k=j+1;k<len;k++)
{
if(nums[i]+nums[j]>nums[k])
{
count++;
}
}
}
}
return count;
}
};
果然不出我们所料,暴力枚举的时间复杂度过高!直接不能通过!那么我们能否再想出一种更优的算法呢!当然可以,我们可以根据数组的单调性,然后进行双指针思路进行求解!
2.双指针思路
双指针思路,是基于在有序的前提下!在讲述双指针的前提下!我们首先补充一点数学的知识!
组成三角形的条件:大家都知道组成三角形的条件是任意两边之和大于第三边即可组成三角形,显然这需要比较三次!那么能否只比较一次来判断是否能组成三角形呢?
答案是肯定的,如果两个较小的边相加大于最大的那个边就可以组成三角形,此时只需要比较一次即可!
双指针思路大致分为以下两步:
1.依次选取最大值(max)!
2.然后定义左右指针,根据左右指针的值的和(sum)与最大值比较是否可以组成三角形!
第二步又细分为两种情况!
2.1 当sum的值大于max,可以组成三角形!又因为是数组元素是单调的,所以left后面的数值与right的数值相加都可以组成三角形!即有right-left种情况!再让right--继续进行判断!
2.2当sum的值小于等于max时,不能组成三角形,只需要让left++再次进行判断即可求解!(最后当左右指针相遇时本次循环结束!)
图解:
代码如下:
class Solution {
public:
//首先先将数组中的元素进行排序,可以有效的减少时间的复杂度!
//然后根据单调性,利用双指针来判断能否组成三角形!
int triangleNumber(vector<int>& nums)
{
int len = nums.size() - 1;
//数学知识:组成三角形的条件:两个较小的边相加大于最大边才能组成三角形!
sort(nums.begin(), nums.end());
//排过序后,依次选取最大值,然后对最大值左边的区间进行双指针判断!
//最大值左边的区间进行判断能否组成三角形!
//1.sum >max 可以组成三角形! 既然能够组成三角形 进行right-left统计组数!
//2.sum <=max left++,当大于max时,统计个数即可!
int count = 0;
for (int i = len; i >= 2; i--)
{
int max = nums[i];
int left = 0;
int right = i - 1;
while (left < right)
{
if (nums[left] + nums[right] > max)
{
count += (right - left);
right--;
}
else
{
left++;
}
}
}
return count;
}
};
通过双指针算法,本例题顺利的通过了!
至此,本道题目讲解结束,希望能对读者有一定的收获,也希望能留下各位看官免费的小心心哦!