解释看代码注解咯
给你一个整数数组 nums
(下标从 0 开始)和一个整数 k
。
一个子数组 (i, j)
的 分数 定义为 min(nums[i], nums[i+1], ..., nums[j]) * (j - i + 1)
。一个 好 子数组的两个端点下标需要满足 i <= k <= j
。
请你返回 好 子数组的最大可能 分数 。
示例 1:
输入:nums = [1,4,3,7,4,5], k = 3 输出:15 解释:最优子数组的左右端点下标是 (1, 5) ,分数为 min(4,3,7,4,5) * (5-1+1) = 3 * 5 = 15 。
示例 2:
输入:nums = [5,5,4,5,4,1,1,1], k = 0 输出:20 解释:最优子数组的左右端点下标是 (0, 4) ,分数为 min(5,5,4,5,4) * (4-0+1) = 4 * 5 = 20 。
提示:
1 <= nums.length <= 105
1 <= nums[i] <= 2 * 104
0 <= k < nums.length
//
// Created by py on 24-3-19.
//
#include <iostream>
#include <vector>
#include <queue>
#include <unordered_map>
#include <deque>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <map>
using namespace std;
class Solution {
public:
/*
* 暴力递归
* 跳过
* */
vector<int> arr;
int sizeArr;
int p;
priority_queue<int, vector<int>> priorityQueue;
void process(int left, int right, int minNum) {
if (left < 0) return;
if (left > right) return;
if (right == sizeArr) return;
priorityQueue.push(minNum * (right - left + 1));
if (left != 0) {
process(left - 1, right, minNum < arr[left - 1] ? minNum : arr[left - 1]);
}
if (right != sizeArr - 1) {
process(left, right + 1, minNum < arr[right + 1] ? minNum : arr[right + 1]);
}
}
/*
* 暴力循环
* 跳过
* */
int violentDpProcess(vector<int> nums, int k) {
int ans = INT32_MIN;
int startMinNum = 2 * 10e4 + 7;
for (int i = k; i < nums.size(); ++i) {
int minNum = startMinNum > nums[i] ? nums[i] : startMinNum;
startMinNum = minNum;
for (int j = k; j >= 0; --j) {
minNum = min(minNum, nums[j]);
ans = max(minNum * (i - j + 1), ans);
}
}
return ans;
}
/*
* 核心思想:双指针滑动区域,求得每一个区域的分数最大值,利用贪心算法,滑动指针
* 请看代码
* */
int doublePointProcess(vector<int> nums, int k) {
int n = nums.size(); // 搞个变量存数组的值
int left = k; // 左右指针
int right = k;
int minNum = nums[k];//这个区域的最小值变量,第一次是从 k 开始的 ,因为这个区域必定包含下标为 k 的值
int ans = -1;//答案变量
// true 是不知道怎么搞当时,就循环内结束了
while (true) {
/*
* 这里我是习惯一开始就计算一次答案值
* */
ans = max((right - left + 1) * minNum, ans);
// 循环结束标识
if (left == 0 && right == n - 1) {
break;
}
// left 到边界了,但是我们不确定继续往右走是否会比答案还要大,因为是 乘法 一个减小一个变大 难说哪个大
if (left == 0) {
right++;
// 更新区域最小值
minNum = min(minNum,nums[right]);
}
// 同理left == 0
else if (right == n - 1) {
left--;
// 更新区域最小值
minNum = min(minNum,nums[left]);
}
// 利用贪心算法,我们专门去取尽可能大的数
/*
* 这里可以证明一下:1,4,3,7,4,5 ; k = 1
* 假如现在left = 1,right = 1
* 很明显假如这次区域往右走,区域值比往左走大 左边:(1,4)= 2 ;;右边:(4,3) = 6
* 以后也是同理
* */
else if (nums[left - 1] > nums[right + 1]) {
left--;
minNum = min(minNum,nums[left]);
} else {
right++;
minNum = min(minNum,nums[right]);
}
}
return ans;
}
int maximumScore(vector<int> nums, int k) {
return doublePointProcess(nums, k);
/*
* 想玩暴力的可以看看
* */
return violentDpProcess(nums,k);
arr = nums;
p = k;
sizeArr = nums.size();
process(k, k, nums[k]);
return priorityQueue.top();
}
};
int main() {
Solution solution;
cout << solution.maximumScore(
{1339, 6671, 9827, 4155, 5138, 3088, 86, 3742, 462, 5139, 1983, 112, 8362, 8298, 9858, 411, 1986, 633, 593,
1664, 403, 4775, 9969, 8508, 2288, 3163, 5907, 4817, 5789, 7599, 1750, 5842, 6051, 7737, 1641, 6176, 736,
487, 2078, 3195, 3074, 4649, 5352, 4262, 771, 5541, 3291, 905, 7502, 3128, 4001, 3849, 1518, 4577, 1505,
2104, 6123, 6052, 3796, 2869, 4530, 3752, 8086, 3221, 2136, 8112, 3055, 645, 941, 5053, 8895, 3363, 5241,
9581, 8109, 4728, 6376, 8655, 9778, 8774, 9827, 2489, 7656, 2204, 858, 3755, 7108, 2451, 7350, 9020, 9777,
8593, 7856, 1721, 1507, 1856, 8200, 7446, 9211, 5049, 4554, 6934, 6940, 6660, 1189, 9538, 1547, 5744, 6621,
6852, 6910, 5425, 2976, 4325, 1080, 4575, 7550, 6960, 3943, 8344, 4164, 2606, 8544, 2512, 633, 6797, 2909,
9089, 6036, 1641, 5410, 5865, 7845, 2080, 1470, 6976, 5972, 7485, 4391, 3387, 9871, 5950, 4080, 9122, 5233,
4752, 6394, 1311, 1922, 908, 7340, 1012, 1856, 2879, 7480, 8188, 1077, 2748, 8367, 1219, 5051, 1077, 2433,
9044, 7171, 6221, 1637, 4559, 3842, 7776, 4102, 352, 780, 8010, 4444, 8497, 4531, 1730, 3796, 3365, 1133,
1065, 3208, 5833, 9135, 7029, 4892, 8922, 2344, 1389, 983, 3091, 1509, 2925, 4795, 1776, 2956, 7767, 9311,
9311, 897, 6195, 2563, 9874, 3318, 4005, 4179, 4561, 5257, 6768, 7584, 4962, 4428, 841, 6683, 3657, 4742,
483, 8287, 9636, 4625, 5354, 1469, 683, 3423, 9621, 1138, 2600, 6, 933, 7545, 5753, 5541, 2589, 4754, 8248,
7392, 8827, 9750, 9457, 4129, 4527, 9825, 5993, 266, 3257, 9438, 9293, 955, 9182, 6583, 1785, 7492, 2192,
1167, 2398, 2568, 2260, 6639, 2289, 1143, 742, 8083, 5567, 57, 1640, 2486, 6070, 6854, 8619, 4147, 2188,
2969, 6969, 7710, 2407, 6617, 2631, 1977, 2984, 1051, 9044, 8088, 5646, 8940, 9643, 9298, 6193, 9799, 9083,
7639, 9123, 5261, 6692, 650, 4410, 9158, 242, 4468, 2686, 3117, 365, 2335, 2911, 4896, 8764, 8668, 7682,
948, 121, 7638, 1265, 7065, 6076, 2002, 5713, 9644, 6710, 7931, 7941, 6316, 6789, 7459, 6360, 8354, 4090,
2090, 955, 7240, 7441, 6605, 6307, 7419, 1352, 2021, 9526, 1361, 9793, 2922, 5115, 2714, 3032, 9769, 9902,
6489, 1358, 848, 6371, 2772, 9735, 352, 4905, 6349, 4556, 2722, 3231, 3610, 2142, 6818, 1123, 6053, 87,
625, 1143, 5188, 6749, 3324, 2049, 4498, 1440, 4345, 7608, 1661, 8448, 6398, 2805, 7022, 7440, 5196, 2739,
6302, 1515, 3004, 6917, 4344, 5278, 9726, 6595, 6856, 3723, 9639, 6232, 9926, 7887, 8172, 1112, 9938, 5614,
8480, 7042, 7279, 1882, 1079, 2768, 9831, 3853, 6121, 169, 6833, 8763, 7112, 8526, 6866, 3601, 7581, 2275,
1668, 2778, 3310, 9168, 1448, 9264, 1371, 644, 6003, 1134, 7397, 7203, 9164, 807, 226, 4353, 1974, 1682,
1750, 1437, 3032, 7964, 46, 1065, 8740, 9515, 9349, 1837, 1025, 5400, 6885, 9475, 3392, 615, 9241, 4005,
9006, 5468, 8618}, 232);
return 0;
}