各位读者好, 我是小陈, 这是我的个人主页, 希望我的专栏能够帮助到你:
JavaSE基础: 基础语法, 类和对象, 封装继承多态, 接口, 综合小练习图书管理系统等
Java数据结构: 顺序表, 链表, 堆, 二叉树, 二叉搜索树, 哈希表等
JavaEE初阶: 多线程, 网络编程, TCP/IP协议, HTTP协议, Tomcat, Servlet, Linux, JVM等(正在持续更新)
OJ链接
其实这题本质也是查找, 而查找的本质是排除 ! ! 查找的本质是排除 ! ! 查找的本质是排除 ! !
最简单的暴力枚举 : 三层 for 循环, 从先固定两个数, 再依次遍历第三个数, 判断这三个数是否能组成三角形, 时间复杂度为O(N³), 会超出时间限制
既然暴力枚举不行, 那尝试就使用双指针, 但我们要找三个数, 只能先固定一个数, 在剩余区间上, 使用双指针(left和right) 找到另外两个数, 尽可能让双指针找全所有正确组合
根据实际情况分析选择对撞双指针还是快慢双指针, 本题要求在数组中"查找", 那么使用对撞双指针能很大程度上提高效率
而且刚才标注了一句话 : 查找的本质是排除, 查找的本质是排除, 查找的本质是排除 ! ! !
如果每次判断, 都能尽可能多的排除数据, 就能尽可能地提高效率
本题有两种基本思路 :
1, 定义 i 指针, 先固定较小的数, 剩余区间使用双指针, i 从左往右遍历
2, 定义 i 指针, 先固定较大的数, 剩余区间使用双指针, i 从右往左遍历
在正式开始之前, 需要对原数组进行排序, 这是常见的作法, 因为一般数组有序时, 成单调性, 能够更高效的进行"排除"
定义变量 count 表示找到有效三角形的个数
count = right
(6下标)
- left(4下标)
这行代码表示 : left 不需要再向右遍历了, 已经找到了3, 8, 10
和3, 9, 10
这两个有效三角形了, right - left 的值就是 i 为 0 下标, right 为 6 下标时有效三角形的个数, 下面的示例同理
上述两种遍历的方式, 其实应该选择让 i 先固定最大值, 从右往左遍历, 因为第一种方式, 没有让 right 向左遍历, 如果让 right 向左遍历, 就不能使用双指针这种高效的方式了
public int maxArea(int[] height) {
public int triangleNumber(int[] nums) {
// 1, 从左往右先固定一个数
// 2, 剩下两个数在剩余区间内, 对撞指针
Arrays.sort(nums);
int i = 0;
int count = 0;
while(i < nums.length - 2) {
int left = i + 1;
int right = nums.length - 1;
while(left < right) {
if(nums[i] + nums[left] > nums[right]){
count += right - left; // 利用单调性快速寻找
right--;
}else{
left++;
}
}
i++;
}
return count;
}