java数据结构与算法刷题-----LeetCode628. 三个数的最大乘积

news2024/10/6 16:16:20
java数据结构与算法刷题目录(剑指Offer、LeetCode、ACM)-----主目录-----持续更新(进不去说明我没写完):https://blog.csdn.net/grd_java/article/details/123063846

文章目录

    • 排序
    • 选择
    • 线性搜索最值

在这里插入图片描述

排序

解题思路:时间复杂度O( n ∗ l o g 2 n n*log_2n nlog2n),空间复杂度O( l o g 2 n log_2n log2n),时间和空间复杂度都用在了快速排序上

对于一堆数里面挑出3个乘积最大,是个数学问题,有3种情况

  1. 这些数都是正数,则最大的3个数乘积最大
  2. 这些数都是负数,则最大的3个数乘积最大
  3. 有正有负,则可能是两个最小的和一个最大的乘积最大,也可能是3个最大的数乘积最大
  1. 只有1个正数,则最小的两个负数和这个正数相乘乘积最大
  2. 有多个正数,也有可能两个最小负数和最大正数更大。例如有[-20000,-10000,1,2,3]这样的数组,最大乘积为 − 10000 ∗ − 20000 ∗ 3 -10000*-20000*3 10000200003
  1. 综上所述,我们只需要找出3个最大的数,已经2个最小的数。然后取两种方案中大的即可。
  1. 3个最大的数乘积可能是最大(没有负数,或者负数乘积都特别小的情况)
  2. 2个最小加最大的数可能是最大(2个特别小的负数+一个最大正数)

有了上面的分析,我们的问题就变成了,找到数组中最大的3个数和最小的2个数

  1. 先排序,然后直接得到
  2. 快速查找算法,找到对应数字
  3. 线性搜索找最值
代码:这里是先排序的思路

在这里插入图片描述

class Solution {
    public int maximumProduct(int[] nums) {
        Arrays.sort(nums);
        int n = nums.length;
        return Math.max(nums[0] * nums[1] * nums[n - 1], nums[n - 3] * nums[n - 2] * nums[n - 1]);
    }
}

选择

解题思路:时间复杂度O( n n n),空间复杂度O( l o g 2 n log_2n log2n)
  1. 法一使用快速排序做
  2. 而对于仅仅找特定几个值的话,快速选择时间复杂度更低
  3. 对于找到第几大的值可以参考215题
🏆LeetCode215. 数组中的第K个最大元素https://blog.csdn.net/grd_java/article/details/136932454
代码

在这里插入图片描述

class Solution {
    public int maximumProduct(int[] nums) {
        int n = nums.length;
        int min1 = quickSort(nums,0,n-1,1),min2 = quickSort(nums,0,n-1,2);
        int max1 = quickSort(nums,0,n-1,n);
        int max2 = quickSort(nums,0,n-1,n-1);
        int max3 = quickSort(nums,0,n-1,n-2);
        return Math.max(max1*min1*min2, max1*max2*max3);
    }
    int quickSort(int[] a, int left,int right,int k){
        if(left >= right) return a[left];
        int x = a[left + right >> 1];//获取当前区间中间的数x
        //借助两个下标,让比x小的去x左边,比x大的去右边
        int leftIndex = left - 1, rightIndex = right + 1;//分别代表区间中应该在x左边(<=x)的下标和x右边的下标
        while(leftIndex < rightIndex){
            do leftIndex++;while(a[leftIndex] < x);//当leftIndex指向的值,>=x时,终止循环
            do rightIndex--;while(a[rightIndex] > x);//当rightIndex指向的值,<=x时,终止循环
            if(leftIndex < rightIndex){//如果leftIndex目前在x左边,而且rightIndex目前在x右边,说明他俩的指向的值应该调换位置
                swap(a,leftIndex,rightIndex);//让小的去x左边leftIndex位置,大的去x右边rightIndex位置
            }
        }//直到目前区间实现x是中位数,左边都比x小,右边都比x大为止
        //此时rightIndex必然指向第一个比x小的值(也就是x比它小的左边部分的边界)
        if(k <= (rightIndex - left + 1)) //如果left到rightIndex区间(比x小的左边部分),正好够我们找到第k大数
            return quickSort(a,left,rightIndex,k);//进入左边区间继续寻找
        else //如果左边部分没有第k大数,那就去右边找,此时左边部分的 rightIndex - left + 1已经确定都比第k大数小,所以k - 左边部分为下轮右边部分该找的值
            return quickSort(a,rightIndex+1,right,k-(rightIndex-left+1));//右边部分找第(k - 左边部分个数)大的数。
    }
    void swap(int[] a,int i,int j){
        int t = a[i];
        a[i] = a[j];
        a[j] = t;
    }
}

线性搜索最值

解题思路:时间复杂度O( n n n),空间复杂度O( 1 1 1)
  1. 对于一个数组的最大值和最小值,或者第二大,第2小等等。只要我们找的是边缘值(100个数,找最小的3个,找最大的3个),线性搜索效率会更高。但是如果是100个数里面找排序后最小的27个数,肯定不如快速选择和小根堆。
  2. 对于只找很少量的几个最值,线性搜索会很方便,只需要遍历一次数组
代码:可见,线性搜索,找最大的3个值就要3个if,100个就要100个if,所以只有找少数几个最值的时候可用

在这里插入图片描述

class Solution {
    public int maximumProduct(int[] nums) {
        //最大的3个
        int max1 = Integer.MIN_VALUE, max2 = Integer.MIN_VALUE, max3 = Integer.MIN_VALUE;
        //最小的两个
        int min1 = Integer.MAX_VALUE, min2 = Integer.MAX_VALUE;
        //线性搜索
        for (int num : nums) {
            if (num > max3) {//如果当前值>第3大max3
                if (num < max2) max3 = num;//小于第二大max2,就赋值给max3
                 else if (num < max1) {//大于max2,小于max1,max2的值给max3,num赋值给max2
                    max3 = max2;//max2的值变为第3大
                    max2 = num;//num变为第二大
                } else {//如果也大于max1
                    max3 = max2;//max2给max3
                    max2 = max1;//max1给max2
                    max1 = num;//num给max1
                }
            }
            //如果当前值小于min2
            if (num < min2) {
                if (num > min1)  min2 = num;//但是大于min1,则num给min2
                else {//如果小于min1
                    min2 = min1;//min1给min2
                    min1 = num;//num给min1
                }
            }
        }
        //可见,线性搜索,找最大的3个值就要3个if,100个就要100个if,所以只有找少数几个最值的时候可用
        //两种方案返回大的
        return Math.max(max1 * max2 * max3, max1 * min1 * min2);
    }
}

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

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

相关文章

简介有向无环图DAG

Sui创纪录的每秒交易量部分归功于数学构造&#xff0c;即有向无环图&#xff08;Directed Acyclic Graph&#xff0c;DAG&#xff09;&#xff0c;该构造通过以最高效的方式处理交易来加速网络交易&#xff0c;而不是按照先来先服务的线性进展。 区块链是设计用于确保数据完整…

APx500音频分析仪硬件简介

两通道模拟输出&#xff0c;两通道或以上的模拟输入接口 线性编码数字音频接口&#xff08;AES/EBU,TOSLINK,SPDIF&#xff09;Linear PCM 脉冲密度调制码流&#xff08;需要APx-PDM选件支持&#xff09; Bluetooth蓝牙音频码流&#xff08;需APx-BT选件支持&#xff09; 最…

基于Android的记单词App系统的设计与实现

博主介绍&#xff1a;✌IT徐师兄、7年大厂程序员经历。全网粉丝15W、csdn博客专家、掘金/华为云//InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&#x1f3…

js 求出对应年月的开始日期和结束日期

实现效果&#xff1a; 背景&#xff1a; element日期时间选择组件&#xff0c;通过时间选择年-月&#xff0c;求出对应年月的开始日期和结束日期。 核心代码&#xff1a; /*** 返回给定年份和月份的起始和结束日期。* 202403 -> 2024-03-01 2024-03-31* param {number} y…

11-新热文章-实时计算

热点文章-实时计算 1 今日内容 1.1 定时计算与实时计算 1.2 今日内容 kafkaStream 什么是流式计算 kafkaStream概述 kafkaStream入门案例 Springboot集成kafkaStream 实时计算 用户行为发送消息 kafkaStream聚合处理消息 更新文章行为数量 替换热点文章数据 2 实时…

Linux下解决Java输出文件,中文变问号和中文乱码问题

# 启用 zh_CN.UTF-8 字体 echo "zh_CN.UTF-8 UTF-8" >> /etc/locale.gen # 生成并安装 locale 数据 locale-gen # 更新当前 shell 环境 source /etc/default/locale 相当于以下操作&#xff1a; # Debian sudo apt install locales sudo dpkg-reconfigur…

基于SSM+Jsp+Mysql的超市管理系统

开发语言&#xff1a;Java框架&#xff1a;ssm技术&#xff1a;JSPJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包…

【第二十四篇】使用Burpsuite实现反射、储存、DOM型XSS(靶场实战案例)

目录 反射性XSS储存型XSSDOM XSS反射性XSS 搜索1后,审查元素: 猜测<font>标签中没有进行XSS特殊字符转义,而在<font>标签内,可使用<script>标签: <script>alert(1)</script>储存型XSS 该模块对姓名、电子邮件、网站做过滤处理,但评论处…

Few-Shot目标检测数据集 | Few-Shot目标检测数据集_已经整理成MS-COCO数据格式_含60000+张图_可直接用于目标检测算法训练

项目应用场景 面向 Few-Shot 目标检测场景&#xff0c;项目提供 6000 张图&#xff0c;已经整理成 MS-COCO 数据格式&#xff0c;可用于 Few-Shot 目标检测的训练数据集&#xff0c;或作为 Few-Shot 目标检测数据集的补充。 数据集展示 数据集下载 > 具体参见项目 README.m…

【算法详解】二分查找

1. 二分查找算法介绍 「二分查找算法&#xff08;Binary Search Algorithm&#xff09;」&#xff1a;也叫做 「折半查找算法」、「对数查找算法」。是一种在有序数组中查找某一特定元素的搜索算法。 基本算法思想&#xff1a;先确定待查找元素所在的区间范围&#xff0c;在逐步…

SSM党员管理系统

一、系统介绍 党员管理系统: 可以方便管理人员对党员管理系统的管理&#xff0c;提高信息管理工作效率及查询效率&#xff0c;有利于更好的为用户提供服务。 主要的模块包括&#xff1a; 1、后台功能&#xff1a; 管理员角色&#xff1a;首页、个人中心&#xff0c;党员管理…

MySQL高级(索引结构B + Tree)

以一颗最大度数&#xff08;max - degree&#xff09;为 4 &#xff08;4阶&#xff09;的 b tree 为例&#xff1a; 绿色框框起来的部分&#xff0c;是索引部分&#xff0c;仅仅起到索引数据的作用&#xff0c;不存储数据。红色框框起来的部分&#xff0c;是数据存储部分&…

PostgreSQL入门到实战-第七弹

PostgreSQL入门到实战 PostgreSQL查询语句(四)官网地址PostgreSQL概述PostgreSQL中DISTINCT 语句介绍PostgreSQL中DISTINCT 语句实操更新计划 PostgreSQL查询语句(四) 官网地址 声明: 由于操作系统, 版本更新等原因, 文章所列内容不一定100%复现, 还要以官方信息为准 https:…

【运输层】TCP 的可靠传输是如何实现的?

目录 1、发送和接收窗口&#xff08;滑动窗口&#xff09; &#xff08;1&#xff09;滑动窗口的工作流程 &#xff08;2&#xff09;滑动窗口和缓存的关系 &#xff08;3&#xff09;滑动窗口的注意事项 2、如何选择超时重传时间 &#xff08;1&#xff09;加权平均往返…

React面试

React渲染流程(重点) jsx描述界面 jsx babel render function>vdom vdom fiber 在进行渲染 vdom 转换fiber reconcile 转换过程创建dom commit 到domvdom React Element 对象, 只记录了子节点, 没有记录兄弟节点, 因为渲染不可中断 fiber fiberNode 对象, 是一个链表 父节…

lua学习笔记13(一些特殊用法的学习和三目运算符的实现)

print("*****************************一些特殊用法的学习*******************************") print("*****************************多变量赋值*******************************") local a,b,c114514,8848,"凌少" print(a) print(b) print(c) -…

C#操作MySQL从入门到精通(7)——对查询数据进行简单过滤

前言 我们在查询数据库中数据的时候,有时候需要剔除一些我们不想要的数据,这时候就需要对数据进行过滤,比如学生信息中,我只需要年龄等于18的,类似这种操作,本文就是详细介绍如何对查询的数据进行初步的过滤。 1、等于操作符 本次查询student_age 等于20的数据,使用我…

导出加入域控的电脑清单

要导出加入域控的所有电脑清单&#xff0c;包括计算机名等基本信息&#xff0c;可以使用 PowerShell 中的 Get-ADComputer cmdlet。下面是一个基础示例脚本&#xff0c;用于从Active Directory (AD)中批量导出所有加入域的计算机名称及可能的其他相关信息&#xff0c;并将其保存…

Mudbus协议CRC校验码C#

Mudbus协议CRC校验码C# 什么是modbus协议特点协议格式modbus-crc16校验原理方法帧校验CRC计算方法&#xff1a;例子 C#代码Demo源码下载 什么是modbus Modbus是一种串行通信协议&#xff0c;最初由Modicon&#xff08;目前属于施耐德电气公司&#xff09;于1979年开发 Modbus协…

设计模式之访问者模式讲解

概念&#xff1a;封装一些作用于某种数据结构中的各元素的操作&#xff0c;它可以在不改变数据结构的前提下定义作用于这些元素的新操作。 抽象访问者&#xff1a;声明一个或多个访问操作&#xff0c;定义访问者可以访问哪些元素。具体访问者&#xff1a;实现抽象访问者的所有操…