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


前言

各位读者好, 我是小陈, 这是我的个人主页, 希望我的专栏能够帮助到你:
📕 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 表示找到有效三角形的个数

在这里插入图片描述

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

在这里插入图片描述


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

在这里插入图片描述

  • 让 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;
    }  
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

灵魂相契的树

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值