题目解析
题目描述
小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。
题目分析
-
理解问题:我们需要找到数组中一段连续区间的最大乘积,并返回该区间的起始和结束位置。
-
数据结构选择:我们可以使用两个变量来记录当前的最大乘积和对应的区间。
-
算法步骤:
- 遍历数组,计算每个可能的区间的乘积。
- 如果遇到0,则跳过该位置,因为0会使得乘积变为0。
- 更新最大乘积和对应的区间。
解题思路
-
动态规划的状态:
- 我们需要记录当前区间的最大乘积和最小乘积,因为数组中可能有负数。负数的乘积与负数相乘可以得到更大的值。
- 使用两个数组
max_prod和min_prod来分别记录以每个位置结尾的最大和最小乘积。
-
状态转移:
- 如果当前元素是正数,最大乘积是
max(arr[i], max_prod[i-1] * arr[i]),最小乘积是min(arr[i], min_prod[i-1] * arr[i])。 - 如果当前元素是负数,最大乘积是
max(arr[i], min_prod[i-1] * arr[i]),最小乘积是min(arr[i], max_prod[i-1] * arr[i])。 - 如果当前元素是 0,最大和最小乘积都需要重新初始化为该元素本身。
- 如果当前元素是正数,最大乘积是
-
更新最大乘积的区间:
- 对于每个元素,更新当前区间的最大乘积,并记录对应的区间起始和结束位置。
-
返回结果:
- 最后,返回最大乘积的起始和结束位置。
实现代码
#include <iostream>
#include <vector>
#include <climits>
using namespace std;
vector<int> solution(int n, vector<int> arr) {
// 初始化最大乘积、最小乘积
int max_prod = 1, min_prod = 1, global_max = INT_MIN;
int temp_start = 0; // temp_start 用于记录潜在的起始位置
int result_start = 0, result_end = 0;
// 遍历数组
for (int i = 0; i < n; ++i) {
if (arr[i] == 0) {
// 遇到零时,当前区间的乘积为0,重新开始
if (0 > global_max) {
global_max = 0;
result_start = i;
result_end = i;
}
// 重置最大和最小乘积
max_prod = 1;
min_prod = 1;
temp_start = i + 1; // 下一段非零区间的开始
} else {
// 如果当前元素是负数,交换最大和最小乘积
if (arr[i] < 0) {
swap(max_prod, min_prod);
}
// 更新最大和最小乘积
max_prod = max(arr[i], max_prod * arr[i]);
min_prod = min(arr[i], min_prod * arr[i]);
}
// 如果当前的最大乘积大于之前的最大值,更新结果
if (max_prod > global_max) {
global_max = max_prod;
result_start = temp_start;
result_end = i;
}
}
// 返回最大乘积区间的起始和结束位置(1-based)
return {result_start + 1, result_end + 1};
}
int main() {
// 测试用例
cout << boolalpha << (solution(5, {1, 2, 4, 0, 8}) == vector<int>{1, 3}) << endl; // [1, 3]
cout << boolalpha << (solution(7, {1, 2, 4, 8, 0, 256, 0}) == vector<int>{6, 6}) << endl; // [6, 6]
cout << boolalpha << (solution(8, {1, 2, 4, 8, 0, 256, 512, 0}) == vector<int>{6, 7}) << endl; // [6, 7]
cout << boolalpha << (solution(7, {1, 2, 0, 0, 4, 8, 0}) == vector<int>{5, 6}) << endl; // [5, 6]
cout << boolalpha << (solution(11, {1024, 0, 2, 1, 0, 2, 128, 512, 4, 256, 256}) == vector<int>{6, 11}) << endl; // [6, 11]
return 0;
}