一起学算法(枚举篇)

chatgpt/2023/9/26 13:52:27

概念

枚举:就是把满足题目条件的所有情况都列举出来,然后一一判断寻找最优解的过程

1.最值问题

1.两个数的最值问题

两个数的最小值,利用Java的运算符就可以实现

int Min(int a,int b){return a<b?a:b;
}

2.n个数的最值问题

当有n个数时Ai时,我们可以首先取前两个数,计算最小值;然后再拿这个最小值和第三个数去比较,得到的最小值再去和第四个数进行比较,一次类推,就可以计算出n个数中最小的值

假设前i个数的最小值为min,则有递推公式如下:

所以将这个递推公式翻译成java代码是这样的:

   public int min(int a,int b){return a<b?a:b;}public int findMin(int[] num){int min=num[0];for(int i=1;i<num.length;i++){min=min(min,num[i]);}return min;}

 3.最值问题的下标

有些时候我们求的并不是一个最小的数,而是要求出这个数组中最小数的下标,那么可以直接记录下标,并且比较的时候直接通过下标去索引到值,然后再进行比较,像这样:

   public int findMin(int[] num){int minIndex=0;for(int i=1;i<num.length;i++){if(num[i]<num[minIndex]){minIndex=i;}}return minIndex;}

2.最值问题的进阶

1.第三大的数

       有时候,我们求最大的数不够,想要求次大的,或者是第三大的数,我们应该怎么做呢?这样的问题,核心思路就是先把最大的求出来,然后忽略最大数的情况下,再去求最大的,这时候就得到次大的了,再把次大的忽略掉,再次求最大的,就是第三大值了

2.数组中两元素的最大乘积

       要求找到数组中两个元素的最大乘积,数组元素一定是正数,那么我们知道最大的元素相乘一定是最大的,所以就是找到最大值和次大值,但是这个问题和第三大的数稍微有点区别,相同的数会被计算进去,所以我们找到最大值以后,可以将它的下标忽略掉,然后再去找最大的值,这样找到的一定是两个可重复的最大元素和次大元素,将两者相乘即可。

3.降维思想

一些统计类问题,第一个思路就是枚举所有的情况,然后再次考虑是不是能够某些O(n)降为O(1),这就是降维思想,具体看

统计上升四元组的数目

1.O(n^4):

最坏的时间复杂度就是枚举i、j、k、l四个变量,然后判定nums四个数的关系,进行统计累加,但是这种做法在范围很大的时候势必超时

2.O(n^2)

  1. 首先,我们枚举j和k,然后对所有满足nums[i]>nums[j]的下标对,执行下一步
  2. 那么只要我们找到数组下标为0~j-1的数中,小于nums[k]的个数,记作a(也就是所有满足条件的i);找到数组下标为k+1~n-1的数中,大于nums[j]的个数,记作b(也就是所有满足条件的);将a*b就是所有满足条件的(i,l)对,把所有的(i,l)累加,就是我们要求出的答案
  3. 问题就转换为找到数组下标0~i-1的数中,小于nums[k]的个数和找到数组下标为k+1~n-1的数中,大于nums[i]的个数

Leetcode题单:

K个元素的最大和

class Solution {public int maximizeSum(int[] nums, int k) {if(nums==null||nums.length==0){return 0;}int ans=0;//执行k次循环while(k!=0){//保存最大值的下标int maxIndex=0;for(int i=0;i<nums.length;i++){if(nums[i]>nums[maxIndex]){maxIndex=i;        }}ans+=nums[maxIndex];nums[maxIndex]+=1;k--;}return ans;}
}

第三大的数

class Solution {public int thirdMax(int[] nums) {
if(nums==null||nums.length==0){return -1;}int[] s=Arrays.stream(nums).distinct().sorted().toArray();if(s.length<3){return s[s.length-1];}return s[s.length-3];}
}

统计上升四元组

class Solution {public long countQuadruplets(int[] nums) {// 初始化四元组的数量long quadruplets = 0;// 数组的长度int n = nums.length;// 记录每个数字的后面比它小的数字的个数int[][] lessCount = new int[n][n + 1];// 记录每个数字的前面比它大的数字的个数int[][] greaterCount = new int[n][n + 1];// 计算lessCount数组getLess(nums, n, lessCount);// 计算greaterCount数组getGreater(nums, n, greaterCount);// 遍历数组,计算满足条件的四元组数量for (int j = 1; j < n - 2; ++j) {for (int k = j + 1; k < n - 1; ++k) {if (nums[k] < nums[j]) {// 更新四元组数目quadruplets += (long) (lessCount[j - 1][nums[k]] * greaterCount[k + 1][nums[j]]);}}}// 返回结果return quadruplets;}// 计算lessCount数组void getLess(int[] nums, int n, int[][] lessCount) {// 遍历数组,计算每个数字的后面比它小的数字的个数for (int i = 0; i < n; ++i) {if (i != 0) {// 复制上一行的数组值lessCount[i] = Arrays.copyOf(lessCount[i - 1], n + 1);}// 统计后面比当前数字小的数字的个数for (int j = nums[i]; j < n; ++j) {++lessCount[i][j];}}}// 计算greaterCount数组void getGreater(int[] nums, int n, int[][] greaterCount) {// 遍历数组,计算每个数字的前面比它大的数字的个数for (int i = n - 1; i >= 0; --i) {if (i != n - 1) {// 复制下一行的数组值greaterCount[i] = Arrays.copyOf(greaterCount[i + 1], n + 1);}// 统计前面比当前数字大的数字的个数for (int j = 1; j < nums[i]; ++j) {++greaterCount[i][j];}}}
}
/*
在给定的Java代码中,我们使用两个二维数组 lessCount 和 greaterCount 分别记录每个数字的后面比它小的数字的个数和前面比它大的数字的个数。在 getLess 方法中,我们遍历数组 nums,对于每个数字 nums[i],我们复制上一行的数组值到当前行(即 lessCount[i] = Arrays.copyOf(lessCount[i - 1], n + 1))。然后,我们统计后面比当前数字小的数字的个数,即从 nums[i]  到 n-1,并将对应位置的计数器加1(++lessCount[i][j])。在 getGreater 方法中,我们逆向遍历数组 nums,对于每个数字 nums[i],我们复制下一行的数组值到当前行(即 greaterCount[i] = Arrays.copyOf(greaterCount[i + 1], n + 1))。然后,我们统计前面比当前数字大的数字的个数,即从 1 到 nums[i] - 1,并将对应位置的计数器加1(++greaterCount[i][j])。接下来,在 countQuadruplets 方法中,我们遍历 nums 数组的中间两个数字,即 j 和 k。我们检查 nums[k] 是否小于 nums[j],如果是,意味着满足题目要求的四元组 (nums[i], nums[j], nums[k], nums[l])。此时,我们可以利用之前计算的 lessCount 和 greaterCount 数组来获取符合条件的数量,即 lessCount[j - 1][nums[k]] 表示在 nums[j - 1] 之前比 nums[k] 小的数字的个数,而 greaterCount[k + 1][nums[j]] 表示在 nums[k + 1] 之后比 nums[j] 大的数字的个数。我们将这两个值相乘,并将其加到 quadruplets 中。最后,我们返回 quadruplets,即满足题目要求的四元组的总数。
*/

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

如若内容造成侵权/违法违规/事实不符,请联系郑州代理记账网进行投诉反馈,一经查实,立即删除!

相关文章

实用上位机--QT

实用上位机–QT 通信协议如下 上位机设计界面 #------------------------------------------------- # # Project created by QtCreator 2023-07-29T21:22:32 # #-------------------------------------------------QT += core gui serialportgreaterThan(QT_MAJOR_V…

oracle数据库dbLink的使用

Oracle的数据库链路&#xff08;dbLink&#xff09;是一种允许在两个不同的数据库实例之间进行通信和数据交换的功能。它可以让你在一个数据库中访问另一个数据库的对象和数据&#xff0c;就像它们属于同一个数据库一样。 创建一个link: CREATE public DATABASE LINK link_sco…

【数据结构篇C++实现】- 图

友情链接&#xff1a;C/C系列系统学习目录 文章目录 &#x1f680;一、图的基本概念和术语1、有向图和无向图3、基本图和多重图4、完全图5、子图6、连通、连通图和连通分量7、强连通图、强连通分量8、生成树、生成森林9、顶点的度、入度和出度10、边的权和网11、稠密图、稀疏图…

狄耐克带着爱与希望,踏上了又一段关于奉献的旅程

路在脚下&#xff0c; 狄耐克紧盯科技前沿&#xff0c; 聚焦国家发展战略和人民美好生活需要&#xff0c; 在智慧社区和智慧医院领域 敢于筑梦、勇于追梦、勤于圆梦&#xff1b; 心系远方&#xff0c; 狄耐克真情投入奉献事业&#xff0c; 将爱与希望的种子撒向全国各地…

中药配方煎药-亿发智能中药汤剂煎煮系统,智慧中药房的数字化升级

随着中药的普及&#xff0c;在治病、养生等方面都发挥这积极作用&#xff0c;但中药煎煮过程繁琐&#xff0c;如果有所差错将会影响药品的药性。为了满足当今用户对中药的需求&#xff0c;增强生产效率和业务水平&#xff0c;亿发中药煎配智能管理系统应运而生&#xff0c;为用…

基于linux下的高并发服务器开发(第四章)- 多进程实现并发服务器(回射服务器)

1. socket // 套接字通信分两部分&#xff1a; - 服务器端&#xff1a;被动接受连接&#xff0c;一般不会主动发起连接 - 客户端&#xff1a;主动向服务器发起连接 2.字节序转换函数 当格式化的数据在两台使用不同字节序的主机之间直接传递时&#xff0c;接收端必然错误…

从零开始学Docker(一):Docker的安装部署

前述&#xff1a;本次学习与整理来至B站【Python开发_老6哥】老师分享的课程&#xff0c;有兴趣的小伙伴可以去加油啦&#xff0c;附链接 宿主机环境&#xff1a;RockyLinux 9 版本管理 Docker引擎主要有两个版本&#xff1a;企业版&#xff08;EE&#xff09;和社区版&#…

Docker安装配置启动Oracle11g容器解决ORA-12541:TNS: 无监听程序连接第三方客户端

Windows下安装可参考我这篇&#xff1a;win11&win7下安装oracle11g数据库全过程 一、下载与启动 前提&#xff1a;需要安装配置好docker(设置镜像源、配置阿里云加速)等&#xff0c;可参考我这篇 基于CentOS7安装配置docker与docker-compose 。 Docker容器相关操作可参考…
推荐文章