Java【手撕双指针】LeetCode 611. “有效三角形个数“, 图文详解思路分析 + 代码

文章目录

  • 前言
  • 一、有效三角形个数
    • 1, 题目
    • 2, 思路分析
    • 1, 从左往右 or 从右往左?
    • 3, 代码展示


前言

各位读者好, 我是小陈, 这是我的个人主页, 希望我的专栏能够帮助到你:
JavaSE基础: 基础语法, 类和对象, 封装继承多态, 接口, 综合小练习图书管理系统等
Java数据结构: 顺序表, 链表, 堆, 二叉树, 二叉搜索树, 哈希表等
JavaEE初阶: 多线程, 网络编程, TCP/IP协议, HTTP协议, Tomcat, Servlet, Linux, JVM等(正在持续更新)

一、有效三角形个数

1, 题目

OJ链接

其实这题本质也是查找, 而查找的本质是排除 ! ! 查找的本质是排除 ! ! 查找的本质是排除 ! !


2, 思路分析

最简单的暴力枚举 : 三层 for 循环, 从先固定两个数, 再依次遍历第三个数, 判断这三个数是否能组成三角形, 时间复杂度为O(N³), 会超出时间限制

既然暴力枚举不行, 那尝试就使用双指针, 但我们要找三个数, 只能先固定一个数, 在剩余区间上, 使用双指针(left和right) 找到另外两个数, 尽可能让双指针找全所有正确组合

根据实际情况分析选择对撞双指针还是快慢双指针, 本题要求在数组中"查找", 那么使用对撞双指针能很大程度上提高效率

而且刚才标注了一句话 : 查找的本质是排除, 查找的本质是排除, 查找的本质是排除 ! ! !

如果每次判断, 都能尽可能多的排除数据, 就能尽可能地提高效率

本题有两种基本思路 :

  • 1, 定义 i 指针, 先固定较小的数, 剩余区间使用双指针, i 从左往右遍历

  • 2, 定义 i 指针, 先固定较大的数, 剩余区间使用双指针, i 从右往左遍历


1, 从左往右 or 从右往左?

在正式开始之前, 需要对原数组进行排序, 这是常见的作法, 因为一般数组有序时, 成单调性, 能够更高效的进行"排除"

定义变量 count 表示找到有效三角形的个数

Java【手撕双指针】LeetCode 611. “有效三角形个数“, 图文详解思路分析 + 代码_第1张图片

count = right(6下标) - left(4下标) 这行代码表示 : left 不需要再向右遍历了, 已经找到了3, 8, 103, 9, 10 这两个有效三角形了, right - left 的值就是 i 为 0 下标, right 为 6 下标时有效三角形的个数, 下面的示例同理

Java【手撕双指针】LeetCode 611. “有效三角形个数“, 图文详解思路分析 + 代码_第2张图片


上述两种遍历的方式, 其实应该选择让 i 先固定最大值, 从右往左遍历, 因为第一种方式, 没有让 right 向左遍历, 如果让 right 向左遍历, 就不能使用双指针这种高效的方式了

Java【手撕双指针】LeetCode 611. “有效三角形个数“, 图文详解思路分析 + 代码_第3张图片

  • 让 i 固定最小值, 从左往右遍历, 会导致 left 在向右遍历时, 虽然也能实现排除(省略不必要的遍历), 但由于 right 无法向左遍历, 会跨过一部分正确的组合, 要想找全遗漏的正确的组合, 就得让 right 向左遍历, 而 left 也必须回到 i + 1 的位置重新向右遍历(因为 left 已经向右移动很多了), 这样其实相当于暴力枚举
  • 让 i 固定最大值, 从右往左遍历, 既能让 left 向右遍历, "排除"也只是派出了left向右遍历的情况, 同时也能让 right 向左遍历, 所以能找全所有的正确组合, 而且排除(省略不必要的遍历)效率很高

3, 代码展示

	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;
    }  

你可能感兴趣的:(OJ题,java,leetcode,查找,有效三角形个数,双指针)