最大乘积区间问题

65 阅读3分钟

问题描述

小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]

解题思路

  1. 理解问题:我们需要找到数组中一段连续区间的最大乘积。由于数组中的元素都是正数或0,乘积的结果可能会非常大,因此我们需要特别注意处理0的情况。
  2. 数据结构选择:我们可以使用两个指针来表示当前考虑的区间,并使用一个变量来记录当前区间的乘积。 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}));
}

}

  1. 初始化maxProduct 用于记录最大乘积,bestStart 和 bestEnd 用于记录最大乘积区间的起始和结束位置。
  2. 遍历数组:使用 start 和 end 指针来遍历数组,计算当前区间的乘积。
  3. 处理0的情况:如果遇到0,则跳过这个区间,从下一个位置开始新的区间。
  4. 更新最大乘积:如果当前区间的乘积大于 maxProduct,或者乘积相同但区间更小,则更新 maxProduct 和对应的区间。