基础算法之双指针--Java实现(下)--LeetCode题解:有效三角形的个数-查找总价格为目标值的两个商品-三数之和-四数之和

news2024/10/2 15:41:07

这里是Themberfue 

今天继续讲解经典算法 => 双指针算法 

没看过上篇文章的小伙伴记得去看看哦😘

 有效三角形的个数

        题目链接:有效三角形的个数

      题目解析

 题目要求在该数组中任意选取三个数,看这三个数是否可以构成可以一个有效三角形。最后返回可以构成三角形的个数。

       算法讲解

我们都知道,三角形的任意两条边的和都大于第三条边。利用这个性质。

所以,只要最大的那条边小于其他两条边的和,那么这个三角形就是有效的。

我们先对数组排序,保证其单调性。

先选取一个数组的最大数,也就是最后一位数,假设为 nums[i] 。

其次定义两个左右指针,假设为left, right,一个指向数组最左边,另一个指向最后一位数的前一位。

此时,选取出了三个数字。那么我们分情况讨论:

1.若 nums[left] + nums[right] > nums[i] 此时说明可以构成一个有效的三角形 => 如果此时固定right的位置,让left向右走,你会发现,由于数组是单调递增的,所以left所指向的值只会不断增大,不会减小,所以 nums[left] + nums[right] > nums[i] 恒成立,所以left向左走没有意义,此时的有效三角形的即为 right - left 也就是这两个指针间隔的数字个数。随后让 right向左走以减小 right所指向的值,继续判断。

2.若 nums[left] + nums[right] <= nums[i] 此时说明不可以构成一个有效的三角形,要让条件尽可能成立,只能是 left向右走,也就是让其指向的值尽可能增大。

        编写代码

class Solution {
    public int triangleNumber(int[] nums) {
        Arrays.sort(nums);
        int count = 0;
        for (int i = nums.length - 1; i > 1; i--) {
            int left = 0;
            int right = i - 1;
            while (left < right) {
                if (nums[left] + nums[right] > nums[i]) {
                    count += right - left;
                    right--;
                } else {
                    left++;
                }
            }
        }
        return count;
    }
}

查找总价格为目标值的两个商品 

        题目链接:查找总价格为目标值的两个商品

        题目解析

总所周知,leetcode的简单题不一定是简单题,但这题确实是简单题,就是求两数之和。 

        算法讲解

这题用枚举也当然可以写,本质上其实也是双指针,但是时间复杂度为O(n^2),算是比较高的了。

题目明确说了,数组是按升序排序的,那么我们可以利用这一特点。

定义两个指针,一个指向最左边,一个指向最右边。

现在将这两个指针所指向的元素的和与 target 比较 => 那么出现了两种情况:

若是 price[left] + price[right] > target => 那么就需要操作一个指针的移动了,如果是left移动,根据升序数组,它只会增大,不会减小,那么就永远不可能达到 target 了,所以需要right 指针移动。

若是 price[left] + price[right] < target => left指针移动即可。

若是 price[left] + price[right] = target => 返回 left 和 right 指向的元素即可。

        编写代码 

class Solution {
    public int[] twoSum(int[] price, int target) {
        int left = 0;
        int right = price.length - 1;
        while (left < right) {
            if (price[left] + price[right] > target) {
                right--;
            } else if (price[left] + price[right] < target) {
                left++;
            } else {
                return new int[]{price[left], price[right]};
            }
        }
        return new int[0];
    }
}

三数之和

        题目链接:三数之和

        题目解析

寻找三个下标不同的数字,这三个数字的和为0,既满足条件,但这题是要找到所有符合的。

        算法讲解

与讲解的第一题类似,由于题目并没有要求返回数组的下标,所以我们先对数组进行排序,利用其单调性解题。

我们先在下标为0的位置选取该数字记为 nums[i]。

定义两个指针,left 指向 i + 1的位置,right 则指向数组最后的位置。

现在选取了三个数字,我们不用真正的将这三个数字加起来判断其是否为零(当然这样也行),如果 nums[left] + nums[right] 的结果为 nums[i] 的相反数,那么自然的,这三个数之和一定为零。

代码优化以及细节:

由于数组中可能存在重复数字,我们在对 i++,left++,right-- 时,可以跳过重复的数字,避免重复计算。

如果此时 nums[i]以及大于零了,就说明其之后的数字就一定大于零,所以 nums[left] + nums[right] 也不可能 和 nums[i] 互为相反数了。

        编写代码 

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        Arrays.sort(nums);
        List<List<Integer>> ret = new ArrayList<>();
        int i = 0;
        while (i < nums.length) {
            int left = i + 1, right = nums.length - 1;
            while (left < right) {
                if (nums[left] + nums[right] < -nums[i]) {
                    int tmpLeft = nums[left];
                    left++;
                    while (left < right && nums[left] == tmpLeft) {
                        left++;
                    }
                } else if (nums[left] + nums[right] > -nums[i]) {
                    int tmpRight = nums[right];
                    right--;
                    while (left < right && nums[right] == tmpRight) {
                        right--;
                    }
                } else {
                    List<Integer> list = new ArrayList<>();
                    list.add(nums[i]);
                    list.add(nums[left]);
                    list.add(nums[right]);
                    ret.add(list);
                    int tmpLeft = nums[left], tmpRight = nums[right];
                    while (nums[left] == tmpLeft && nums[right] == tmpRight && left < right) {
                        left++;
                        right--;
                    }
                }
            }
            if (nums[i] > 0) {
                break;
            }
            int tmpI = nums[i];
            i++;
            while (i < nums.length && nums[i] == tmpI) {
                i++;
            }
        }
        return ret;
    }
}

四数之和

        题目链接:四数之和

        题目解析

与双数之和类似,现在需要选取四个数字,它们的和为 target,并且是选取所有符合条件的

        算法解析 

解法其实与三数之和类似,三数选取 nums[i]作为基准值,那么四数之和则需要 选取 nums[i]以及 nums[j] 作为基准值。

这里也不需要将这四个数相加判断其是否等于 target,只需要 nums[left] + nums[right] == target - nums[i] - nums[j] 即可。

代码优化以及细节处理和三数之和也是几乎一样。

        编写代码 

class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        Arrays.sort(nums);
        List<List<Integer>> ret = new ArrayList<>();
        int i = 0;
        while (i < nums.length) {
            int j = i + 1;
            while (j < nums.length) {
                int left = j + 1, right = nums.length - 1;
                long aim = (long)target - nums[j] - nums[i];
                while (left < right) {
                    if (nums[left] + nums[right] < aim) {
                        int tmpLeft = nums[left];
                        left++;
                        // 去重
                        while (left < right && nums[left] == tmpLeft) {
                            left++;
                        }
                    } else if (nums[left] + nums[right] > aim) {
                        int tmpRight = nums[right];
                        right--;
                        // 去重
                        while (left < right && nums[right] == tmpRight) {
                            right--;
                        }
                    } else {
                        ret.add(Arrays.asList(nums[left], nums[right], nums[i], nums[j]));
                        int tmpLeft = nums[left], tmpRight = nums[right];
                        // 去重
                        while (nums[left] == tmpLeft && nums[right] == tmpRight && left < right) {
                            left++;
                            right--;
                        }
                    }
                }
                int tmpJ = nums[j];
                j++;
                // 去重
                while (j < nums.length && nums[j] == tmpJ) {
                    j++;
                }
            }
            int tmpI = nums[i];
            i++;
            // 去重
            while (i < nums.length && nums[i] == tmpI) {
                i++;
            }
        }
        return ret;
    }
}

好了,以上就是今天内容的全部讲解,如果有不懂的地方,随时私聊😘

我们下一个算法讲解见 => 滑动窗口😁


 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2184645.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2024上半年网络安全漏洞态势报告

2024年9月26日&#xff0c;“2024中国数字经济创新发展大会”在汕头成功召开&#xff0c;大会汇聚业界精英&#xff0c;旨在全面探讨在新形势新挑战下&#xff0c;如何“健全数据安全体系 构建可信流通环境”。在《数据安全与合规发展专题》分论坛上&#xff0c;工业和信息化部…

Windows远程Kylin系统-xrdp

Windows远程Kylin系统-xrdp 一. 查看开放端口 查看是否有3389端口二. 安装xrdp Kylin对应的是centos8 下载链接&#xff1a;https://rhel.pkgs.org/8/epel-x86_64/xrdp-0.10.1-1.el8.x86_64.rpm.html rpm -Uvh 包名 systemctl start xrdp 启动服务 systemctl enable xrdp …

只出现一次的数字|||(考察点为位操作符)

目录 一题目&#xff1a; 二思路汇总&#xff1a; 三代码解答&#xff1a; 一题目&#xff1a; leetcode原题链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 二思路汇总&#xff1a; 思路&#xff1a;如果直接对数组按位异或&#xff0c;那么最后得到的是a^b&a…

pnpm install的时候失败提示python问题

忘记是哪个依赖了&#xff0c;npm正常&#xff0c;pnpm的时候就异常&#xff0c;但是报错里python异常 解决方法&#xff1a;安装python就行 ennn免安装的python好麻烦 网上找教程安装python好麻烦&#xff0c;发现微软可以直接安装&#xff0c;就用微软的安装了 查看结果 p…

数字化转型新时代:TOGAF框架助力企业颠覆式创新

1. 从传统到未来&#xff1a;TOGAF如何驱动企业的数字化转型 在传统业务模式面临挑战的时代&#xff0c;TOGAF&#xff08;The Open Group Architecture Framework&#xff09;提供了帮助企业完成从传统到数字化业务模式转型的强大工具。通过系统化的架构开发方法&#xff08;…

JSP(Java Server Pages)基础使用三(表单传参)

表单传参 1.这次学习的是我们在网络上使用次数相对来说很多的jsp的使用方式&#xff0c;表单传参是运用了form表单的post方法来讲表单中的数据传递给action页面,action的作用是跳转就类似a标签&#xff0c;当然action不只可以是页面&#xff0c;还可以是后端类&#xff0c;用来…

数据库(MySQL):使用命令从零开始在Navicat创建一个数据库及其数据表(一)

一. 使用工具和命令 1.1 使用的工具 Navicat Premium 17 &#xff1a;“Navicat”是一套可创建多个连接的数据库管理工具。 MySQL版本8.0.39 。 1.2 使用的命令 Navicat中使用的命令 命令命令解释SHOW DATABASES&#xff1b;展示所有的数据库CREATE DATABASE 数据库名称; 创…

Goland使用SSH远程Linux进行断点调试 (兼容私有库)

① 前置需求 ssh远程的 Linux 服务器必须安装 高于本地的 Go推荐golang 安装方式使用 apt yum snap 等系统自管理方式&#xff0c;&#xff08;要安装最新版本的可以找找第三方源&#xff09;&#xff0c;如无特殊需求不要自行编译安装golang ② Goland设置 2.1、设置项处理…

Spring Boot助力IT领域交流平台开发

2 系统关键技术 2.1 JAVA技术 Java是一种非常常用的编程语言&#xff0c;在全球编程语言排行版上总是前三。在方兴未艾的计算机技术发展历程中&#xff0c;Java的身影无处不在&#xff0c;并且拥有旺盛的生命力。Java的跨平台能力十分强大&#xff0c;只需一次编译&#xff0c;…

Qt 中的 QListWidget、QTreeWidget 和 QTableWidget:简化的数据展示控件

Qt 中的 QListWidget、QTreeWidget 和 QTableWidget&#xff1a;简化的数据展示控件 在 Qt 的用户界面开发中&#xff0c;展示和管理数据是常见的需求。Qt 提供了丰富的控件供开发者选择&#xff0c;其中 QListWidget、QTreeWidget 和 QTableWidget 是三个高层封装控件&#x…

【Android】布局优化—include,merge,ViewStub的使用方法

引言 1.重要性 在Android应用开发中&#xff0c;布局是用户界面的基础。一个高效的布局不仅能提升用户体验&#xff0c;还能显著改善应用的性能。随着应用功能的复杂性增加&#xff0c;布局的优化变得尤为重要。优化布局能够减少渲染时间&#xff0c;提高响应速度&#xff0c…

Vue 路由设置

为了防止遗忘&#xff0c;记录一下用Vue写前端配置路由时的过程&#xff0c;方便后续再需要用到时回忆。 一、举个例子 假如需要实现这样的界面逻辑&#xff1a; 在HomePage中有一组选项卡按钮用于导航到子页面&#xff0c;而子页面Page1中有一个按钮&#xff0c;其响应事件是…

vulnhub-Replay 1靶机

vulnhub&#xff1a;https://www.vulnhub.com/entry/replay-1,278/ 导入靶机&#xff0c;放在kali同网段&#xff0c;扫描 靶机在192.168.81.8&#xff0c;扫描端口 开启了三个端口&#xff0c;存在网站服务&#xff0c;访问 网页上有个超链接&#xff0c;点击后下载了这样一个…

嵌入式外设应用(代码)

文章目录 1. 工业自动化2. 智能家居设备3. 汽车电子4. 生命体征监测仪5. 物联网应用嵌入式外设应用广泛,有很多应用领域: 1. 工业自动化 应用场景:使用传感器监测设备状态,控制电机的启动和停止。 示例代码: #include <stdio.h> #include <stdbool.h>// 模…

农业机械检测系统源码分享

农业机械检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vis…

spring-boot 整合 mybatis

文章目录 Spring boot 整合Mybatis将数据返回到浏览器1. 准备数据2. 导入依赖3. 配置数据库连接4. 创建一个 pojo 包&#xff0c;创建User实体类5. 创建一个mapper包&#xff0c;写一个UserMapper接口6. 创建一个service包&#xff0c;写一个UserService接口。7. 在 Service 包…

如何对大模型的回答置信度做出判断

大模型的回答置信度&#xff0c;特别是像 GPT 模型这类基于生成式预训练模型的系统&#xff0c;是一个高度复杂的概念。置信度&#xff08;confidence&#xff09;通常指模型在给定输出上有多大的确定性&#xff0c;反映的是模型对其生成的答案有多“确信”。这种置信度既可以被…

【STM32-HAL库】自发电型风速传感器(使用STM32F407ZGT6)(附带工程下载链接)

一、自发电型风速传感器介绍 自发电型风速传感器&#xff0c;也称为风力发电型风速传感器或无源风速传感器&#xff0c;是一种不需要外部电源即可工作的风速测量设备。这种传感器通常利用风力来驱动内部的发电机构&#xff0c;从而产生电能来供电测量风速的传感器部分。以下是自…

从u盘直接删除的文件能找回吗 U盘文件误删除如何恢复

U盘上的文件被删除并不意味着它们立即消失。事实上&#xff0c;删除操作只是将文件从文件系统的目录中移除&#xff0c;并标记可用空间。这意味着在文件被覆盖之前&#xff0c;它们仍然存在于存储介质上。因此&#xff0c;只要文件没有被新的数据覆盖&#xff0c;我们就有机会恢…

一本应用《软件方法》的书《软件需求分析和设计实践指南》

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 昨天看到了韩雪燕、李楠等老师写的《软件需求分析和设计实践指南》&#xff0c;前言提到了我。特别说明的是&#xff0c;这个书我自己看到的&#xff0c;韩老师等之前也未和我提过--这…