这是我参与8月更文挑战的第4天,活动详情查看:8月更文挑战
作为一个算法菜鸟来说,每日一题是我督促自己最后的倔强!!!做多了其实对于我自己来说,更多的是思维转换,以前首当其冲的是暴力+循环,能跑出来结果并通过就O了(虽然现在也是)。每次打开算法题,基本步骤就是 思考→ 循环暴力→超时(或用例不通过)重复数次→通过(击败1%),属实是难受啊....
题目
给定一个包含非负整数的数组,你的任务是统计其中可以组成三角形三条边的三元组个数。
示例 1:
输入: [2,2,3,4]
输出: 3
解释:
有效的组合是:
2,3,4 (使用第一个 2)
2,3,4 (使用第二个 2)
2,2,3
拿到今天的题目,感觉描述很少嘛~不过没关系,数学底子还是有的。
审题
- 首当其冲的就是三角形的三条边嘛,a+b>c的公式还是记得的
- 非负整数,圈住重点(三次测试用例失败均在此),需要防止有0的出现
- 对于循环狗来说,a+b>c的前提是数组需要升序
代码实现
好了,蠢逼的做法,大家看看就行~
- 先来一波校验数组
- 用Arrays.sort对数组进行一次升序
- 第一层循环获取当前值,并对0判断
- 第二层循环对第一层的指针动态后移,,并对0判空
- 第三层循环 再对第二层指针动态后移,并对0判空
- 并在第三层循环中做出a+b>c的判断
public int triangleNumber(int[] nums) {
if(nums.length<3){
return 0;
}
Arrays.sort(nums);
int max =0;
for (int i = 0; i <nums.length; i++) {
int a = nums[i];
if(a == 0){
continue;
}
for (int j = i+1; j <nums.length ; j++) {
int b = nums[j];
if(b == 0){
continue;
}
for (int k = j+1; k < nums.length; k++) {
int c = nums[k];
if(c == 0){
continue;
}
if (a+b>c){
max++;
}
}
}
}
return max;
}
官方题解
由于a+b>c的原理,转换到数组则是 nums[k] < nums[i] + nums[j],在固定下标 i 的前提下,下标K随着下标j的递增而递增。这两个是同向递增移动的指针。我们每一次将 j 向右移动一个位置,即 j←j+1,并尝试不断向右移动 k,使得 k 是最大的满足 nums[k] < nums[i] + nums[j] 的下标。我们将 max(k - j, 0) 累加入答案。
class Solution {
public int triangleNumber(int[] nums) {
int n = nums.length;
Arrays.sort(nums);
int ans = 0;
for (int i = 0; i < n; ++i) {
int k = i;
for (int j = i + 1; j < n; ++j) {
while (k + 1 < n && nums[k + 1] < nums[i] + nums[j]) {
++k;
}
ans += Math.max(k - j, 0);
}
}
return ans;
}
}
总结
对于本次的题目,其实一开始就想到了双指针的方式,但是没能拓宽思路,只知道埋头苦干,没能拓宽了我的对双指针的视野。