题目
给定一个包含非负整数的数组,你的任务是统计其中可以组成三角形三条边的三元组个数。
示例 1:
输入: [2,2,3,4]
输出: 3
解释:
有效的组合是:
2,3,4 (使用第一个 2)
2,3,4 (使用第二个 2)
2,2,3
注意:
数组长度不超过1000。
数组里整数的范围为 [0, 1000]。
思路
迭代1
判断三角形,只需要看两边之和是否大于另外一边,先用暴力法写出来:
int triangleNumber(int* nums, int numsSize) {
if (numsSize < 3) return 0;
int cnt = 0;
for (int i = 0; i < numsSize - 2; i++) {
for (int j = i + 1; j < numsSize - 1; j++) {
for (int k = j + 1; k < numsSize; k++) {
//printf("now :%d %d %d:%d %d %d\n", i, j, k, nums[i], nums[j], nums[k]);
if ((nums[i] + nums[j] > nums[k]) ) {
cnt++;
//printf("cnt++ = %d\n", cnt);
}
}
}
}
return cnt;
}
可以看出时间复杂度为O(n^3),提交上去必然超时,思考能否去掉一层循环。
迭代2
考虑到输入数据的有序性能实现剪枝,我们首先对数据进行排序。
quick_sort(nums, 0, numsSize - 1);
排序后以 1 2 3 4 5 6 为例,如果前两个指针指向1和2,第三层循环第一个是3,如果3都不满足结果,那么4 5 6是不用计算的,我们加个break跳出循环可以实现剪枝。
if ((nums[i] + nums[j] > nums[k]) ) {
cnt++;
printf("cnt++ = %d\n", cnt);
}
else {
break;
}
提交上去发现AC
迭代3
本例中我们没有处理重复元素,如果排序后一个元素重复出现怎样处理?
- 元素重复2或3次,如 2 2 2 3 4
正常计算,答案是7 - 元素重复4次,如 2 2 2 2 3 4
答案是14 - 元素重复k次,如 2 2 2 2 2 3 4
设为 f(k) - 元素重复k+1次
例子 | 元素重复次数 | 答案 | 与上一行之差 |
---|---|---|---|
2 2 3 4 | 2 | 3 | |
2 2 2 3 4 | 3 | 7 | |
2 2 2 2 3 4 | 4 | 14 | |
2 2 2 2 2 3 4 | 5 | 25 | 9 |
2 2 2 2 2 2 3 4 | 6 | 41 | 16 |
2 2 2 2 2 2 2 3 4 | 7 | 63 | 22 |
2 2 2 2 2 2 2 2 3 4 | 8 | 92 |