问题描述
小R手上有一个长度为 n 的数组 (n > 0),数组中的元素分别来自集合 [0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024]。小R想从这个数组中选取一段连续的区间,得到可能的最大乘积。
你需要帮助小R找到最大乘积的区间,并输出这个区间的起始位置 x 和结束位置 y (x ≤ y)。如果存在多个区间乘积相同的情况,优先选择 x 更小的区间;如果 x 相同,选择 y 更小的区间。
注意:数组的起始位置为 1,结束位置为 n。
测试样例
样例1:
输入:
n = 5, arr = [1, 2, 4, 0, 8]
输出:[1, 3]
样例2:
输入:
n = 7, arr = [1, 2, 4, 8, 0, 256, 0]
输出:[6, 6]
样例3:
输入:
n = 8, arr = [1, 2, 4, 8, 0, 256, 512, 0]
输出:[6, 7]
解题思路
- 理解问题:我们需要找到数组中一段连续区间的最大乘积。由于数组中的元素都是正数或0,乘积的结果可能会非常大,因此我们需要特别注意处理0的情况。
- 数据结构选择:我们可以使用两个指针来表示当前考虑的区间,并使用一个变量来记录当前区间的乘积。
3.1. - 初始化两个指针
start和end,以及一个变量maxProduct来记录最大乘积。- 遍历数组,计算从
start到end的乘积。 - 如果遇到0,则需要重新开始计算新的区间。
- 如果当前区间的乘积大于
maxProduct,则更新maxProduct和对应的区间。 - 如果乘积相同,优先选择
start更小的区间;如果start相同,选择end更小的区间。
- 遍历数组,计算从
代码
import java.util.Arrays;
public class Main { public static int[] solution(int n, int[] data) { int maxProduct = 0; int bestStart = -1, bestEnd = -1; int start = 0;
while (start < n) {
int end = start;
int currentProduct = 1;
// 计算从 start 到 end 的乘积
while (end < n) {
currentProduct *= data[end];
// 如果当前乘积为0,则跳过这个区间
if (currentProduct == 0) {
break;
}
// 如果当前乘积大于 maxProduct,或者乘积相同但区间更小,则更新
if (currentProduct > maxProduct ||
(currentProduct == maxProduct && (start < bestStart || (start == bestStart && end < bestEnd)))) {
maxProduct = currentProduct;
bestStart = start;
bestEnd = end;
}
end++;
}
// 跳过0,从下一个位置开始新的区间
while (start < n && data[start] == 0) {
start++;
}
start = end + 1;
}
return new int[]{bestStart + 1, bestEnd + 1};
}
public static void main(String[] args) {
// Add your test cases here
System.out.println(Arrays.equals(solution(5, new int[]{1, 2, 4, 0, 8}), new int[]{1, 3}));
System.out.println(Arrays.equals(solution(7, new int[]{1, 2, 4, 8, 0, 256, 0}), new int[]{6, 6}));
}
}
- 初始化:
maxProduct用于记录最大乘积,bestStart和bestEnd用于记录最大乘积区间的起始和结束位置。 - 遍历数组:使用
start和end指针来遍历数组,计算当前区间的乘积。 - 处理0的情况:如果遇到0,则跳过这个区间,从下一个位置开始新的区间。
- 更新最大乘积:如果当前区间的乘积大于
maxProduct,或者乘积相同但区间更小,则更新maxProduct和对应的区间。