全网最全面的华为OD机试真题汇总,100%原题题库,不需要开会员即可查看全部内容,更多考题请查看真题库。
真题库:https://www.yuque.com/codernav.com/od
题目:几何平均值最大子数组
知识点数组二分查找
时间限制:1s 空间限制:256MB 限定语言:不限
题目描述:
从一个长度为N的正数数组numbers中找出长度至少为L且几何平均值最大子数组,并输出其位置和大小。(K个数的几何平均值为K个数的乘积的K次方根)
若有多个子数组的几何平均值均为最大值,则输出长度最小的子数组。
若有多个长度相同的子数组的几何平均值均为最大值,则输出最前面的子数组。
输入描述:
第一行输入为N、L,N表示numbers的大小(1 <= N <= 100000),L表示子数组的最小长度(1 <= L <= N),
之后N行表示numbers中的N个数,每个一行(10-9 <= numbers[i] <= 109)。
输出描述:
输出子数组的位置(从0开始计数)和大小,中间用一个空格隔开。
补充说明:
用例保证除几何平均值为最大值的子数组外,其他子数组的几何平均值至少比最大值小最大值的10-10倍
示例1
输入:
3 2
2
2
3
输出:
1 2
说明:
长度至少为2的子数组共三个,分别是{2,2}、{2,3}、{2,2,3},其中{2,3}的几何平均值最大,故输出其位置1和长度2
示例2
输入:
10 2
0.2
0.1
0.2
0.2
0.2
0.1
0.2
0.2
0.2
0.2
输出:
2 2
说明:
有多个长度至少为2的子数组的几何平均值为0.2,其中长度最短的为2,也有多个,长度为2且几何平均值为0.2的子数组最前面的那个为从第二个数开始的两个0.2组成的子数组
解题思路:
这道题正确率为0,大家看看还有什么没有注意到的!
如例1:
3 2
2
2
3
当长度为2时:
2,2 :2*2=4;2,3 :2*3=6;最大值为6,几何平均值为2.449489742783178,索引为1,长度为2
当长度为3时:
2,2,3 :2*2*3=12;最大值为12,索引为0,长度为3,几何平均值为2.2894284851066637<2.449489742783178
最终结果:索引1,长度2
代码实现:
package com.codernav.demo.hwod.exam;
import java.math.BigDecimal;
import java.util.Scanner;
/**
* @title 几何平均值最大子数组
* @Description 从一个长度为N的正数数组numbers中找出长度至少为L且几何平均值最大子数组,并输出其位置和大小。(K个数的几何平均值为K个数的乘积的K次方根)
* 若有多个子数组的几何平均值均为最大值,则输出长度最小的子数组。
* 若有多个长度相同的子数组的几何平均值均为最大值,则输出最前面的子数组。
* @Author 开发者导航
* @website https://codernav.com
* @date 2023/5/28
*/
public class Main {
public static double max; //最大几何平均值
public static int index; //正在处理数据的索引
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int L = sc.nextInt();
double[] doubles = new double[N];
for (int i = 0; i < N; i++) {
doubles[i] = sc.nextDouble();
}
int resIndex = 0;
int resLen = 0;
for (int i = L; i <= N; i++) {
if (handle(i, doubles)) {
resIndex = index;
resLen = i;
}
}
System.out.println(resIndex + " " + resLen);
}
/**
* 是否满足最大几何平均值
*
* @param len 子数组长度
* @param doubles 输入的正数数组
* @return
*/
public static boolean handle(int len, double[] doubles) {
double maxInLen = 1; //len长度数组的最大乘积
for (int i = 0; i < len; i++) {
BigDecimal num1 = new BigDecimal(String.valueOf(maxInLen));
BigDecimal num2 = new BigDecimal(String.valueOf(doubles[i]));
maxInLen = num1.multiply(num2).doubleValue(); //初始化maxInLen
}
index = 0; //初始化索引位置
double count = maxInLen; //各数组中数字的乘积
for (int i = len; i < doubles.length; i++) {
//如例1: 1 2 3 长度为2
//第一个子数组{1,2} 乘积为 1 * 2 = 2
//第二个子数组{2,3} 乘积为 2 * 3 / 1 = 6
//相当于滑窗,第一个数组的乘积 * 紧接着后面的第一个数 / 第一个数组的第一个数 = 紧接着后面的数组的乘积
count *= doubles[i] / doubles[i - len];
if (count > maxInLen) { //count大于maxInLen需要更新index和maxInLen
index = i - len + 1;
maxInLen = count;
}
}
double CFG = Math.pow(maxInLen, (double) 1 / len); //求出乘积的Len次方根
if (CFG > max) {
max = CFG;
return true;
}
return false;
}
}
