字节面试原题⁉️
给你一个整数数组 nums ,请你找出数组中乘积最大的非空连续 子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。
1 2 3
   | 输入: nums = [2,3,-2,4] 输出: 6 解释: 子数组 [2,3] 有最大乘积 6。
   | 
 
1 2 3
   | 输入: nums = [-2,0,-1] 输出: 0 解释: 结果不能为 2, 因为 [-2,-1] 不是子数组。
   | 
 
1 2 3 4 5 6 7 8 9 10 11 12
   | class Solution { public:     int maxProduct(vector<int>& nums) {         int n = nums.size();         vector<long> mx(nums.begin(), nums.end()), mn(nums.begin(), nums.end());         for (int i = 1; i < n; i++) {             mx[i] = max({mx[i - 1] * nums[i], (long)nums[i], mn[i - 1] * nums[i]});             mn[i] = min({mn[i - 1] * nums[i], (long)nums[i], mx[i - 1] * nums[i]});         }         return *max_element(mx.begin(), mx.end());     } };
  | 
 
给你一个下标从 0 开始的整数数组 nums ,它表示一个班级中所有学生在一次考试中的成绩。老师想选出一部分同学组成一个 非空 小组,且这个小组的 实力值 最大,如果这个小组里的学生下标为 i0, i1, i2, … , ik ,那么这个小组的实力值定义为 nums[i0] * nums[i1] * nums[i2] * ... * nums[ik] 。
请你返回老师创建的小组能得到的最大实力值为多少。
1 2 3
   | 输入:nums = [3,-1,-5,2,5,-9] 输出:1350 解释:一种构成最大实力值小组的方案是选择下标为 [0,2,3,4,5] 的学生。实力值为 3 * (-5) * 2 * 5 * (-9) = 1350 ,这是可以得到的最大实力值。
   | 
 
1 2 3
   | 输入:nums = [-4,-5,-4] 输出:20 解释:选择下标为 [0, 1] 的学生。得到的实力值为 20 。我们没法得到更大的实力值。
   | 
 
1 2 3 4 5 6 7 8 9 10 11 12 13
   | class Solution { public:     long long maxStrength(vector<int>& nums) {         long long mn = nums[0], mx = mn;         for (int i = 1; i < nums.size(); i++) {             long long x = nums[i];             long long tmp = mn;             mn = min({mn, x, mn * x, mx * x});             mx = max({mx, x, tmp * x, mx * x});         }         return mx;     } };
  | 
 
给你一个大小为 m x n 的矩阵 grid 。最初,你位于左上角 (0, 0) ,每一步,你可以在矩阵中 向右 或 向下 移动。
在从左上角 (0, 0) 开始到右下角 (m - 1, n - 1) 结束的所有路径中,找出具有 最大非负积 的路径。路径的积是沿路径访问的单元格中所有整数的乘积。
返回 最大非负积 对 10^9 + 7 取余 的结果。如果最大积为 负数 ,则返回 -1 。
注意:取余是在得到最大积之后执行的。
示例 1:

1 2 3
   | 输入:grid = [[-1,-2,-3],[-2,-3,-3],[-3,-3,-2]] 输出:-1 解释:从 (0, 0) 到 (2, 2) 的路径中无法得到非负积,所以返回 -1 。
   | 
 
示例 2:

1 2 3
   | 输入:grid = [[1,-2,1],[1,-2,1],[3,-4,1]] 输出:8 解释:最大非负积对应的路径如图所示 (1 * 1 * -2 * -4 * 1 = 8)
   | 
 
✅ 本题为「鹅厂」与「字节」面试算法题,也是「152. 乘积最大子数组」的升维算法题
1️⃣ 三维数组
第三维度记录 min 与 max,需要单独初始化第一行和第一列。
由于过程中无法确定最大值的由来,那么需要「左」和「上」的最大最小值来乘于当前值 grid[i][j],与「乘积最大子数组」思路一致。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
   | class Solution { public:     int maxProductPath(vector<vector<int>>& grid) {         const int MOD = 1e9 + 7;         int m = grid.size(), n = grid[0].size();                  vector f(m, vector(n, vector(2, 0LL)));         f[0][0] = {grid[0][0], grid[0][0]};         for (int j = 1; j < n; j++) {             f[0][j][0] = f[0][j - 1][0] * grid[0][j];             f[0][j][1] = f[0][j - 1][1] * grid[0][j];         }         for (int i = 1; i < m; i++) {             f[i][0][0] = f[i - 1][0][0] * grid[i][0];             f[i][0][1] = f[i - 1][0][1] * grid[i][0];         }         for (int i = 1; i < m; i++) {             for (int j = 1; j < n; j++) {                 int x = grid[i][j];                 f[i][j][0] = min({f[i - 1][j][0] * x, f[i - 1][j][1] * x,                                   f[i][j - 1][0] * x, f[i][j - 1][1] * x});                 f[i][j][1] = max({f[i - 1][j][0] * x, f[i - 1][j][1] * x,                                   f[i][j - 1][0] * x, f[i][j - 1][1] * x});             }         }         return f[m - 1][n - 1][1] >= 0 ? f[m - 1][n - 1][1] % MOD : -1;     } };
  | 
 
2️⃣ 两个二维数组
相当于将方法一三维数组的第三维度拆分成两个二维数组,与「乘积最大子数组」思路一致。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
   | class Solution { public:     int maxProductPath(vector<vector<int>>& grid) {         const int MOD = 1e9 + 7;         int m = grid.size(), n = grid[0].size();         vector<vector<long long>> mx(m, vector<long long>(n));         vector<vector<long long>> mn(m, vector<long long>(n));         mx[0][0] = mn[0][0] = grid[0][0];         for (int j = 1; j < n; j++)             mx[0][j] = mn[0][j] = mx[0][j - 1] * grid[0][j];         for (int i = 1; i < m; i++)             mx[i][0] = mn[i][0] = mx[i - 1][0] * grid[i][0];         for (int i = 1; i < m; i++) {             for (int j = 1; j < n; j++) {                 int x = grid[i][j];                 mx[i][j] = max({mx[i - 1][j] * x, mn[i - 1][j] * x,                                 mx[i][j - 1] * x, mn[i][j - 1] * x});                 mn[i][j] = min({mx[i - 1][j] * x, mn[i - 1][j] * x,                                 mx[i][j - 1] * x, mn[i][j - 1] * x});             }         }         return mx[m - 1][n - 1] >= 0 ? mx[m - 1][n - 1] % MOD : -1;     } };
  |