Алгоритм Разработка и анализ [0009] Динамическое программирование (II) (Максимальная сумма / подмассив продукта)

Стенографический https://www.dazhuanlan.com/2019/08/25/5d625b5c4d1ea/


 Эта статья 53. Максимальная подмассив и 152. Подмассив Максимальный продукт расщепляется и суб-решение проблем: анализ ключ к решению проблемы динамических идей программирования.

описание проблемы

  • Две проблемы решить подобные проблемы решаются с последовательностью последовательности, приведенной для удовлетворения определенных математических характеристик (максимальные и / продукта максимума), даже если не требуется выходную последовательность.
  • Ключевая фраза обратить внимание: containing at least one numberтак что есть по крайней мере , данные элементы последовательности, которые также могут вдохновить нас в качестве специального лечения.

53. Максимальная подмассив решения проблем идеи

  • А мысль: $ сумма [J] $ является крупнейшим подфрагментом до J элементов последовательности и подзадач, чтобы решить, как, за $ суммы [п] $, по сравнению с ответом. Тем не менее, как использовать $ суммы [1, 2, ..., J-1] $ до $ суммы [J] $ решить эту проблему? Очевидно, что необходимо знать максимальное поле и бывшие J-элементный начальный и конечный подфрагмент позиции, решая проблему субгосударственного перехода явно сложнее.
  • Поместите это еще одна мысль. Две идей: $ суммы [J] $ являются максимальными подотрезками с первым концом -го элемента детского подотрезка и решения проблем, $ Max_ {1 Leq J Leq п} (суммы [у]) $ являются всем и самые крупные последовательности суб-сегмента. Через $ суммы [J-1] $ $ текущий элемент и НУМС [J] , можно вычислить по $ -го элемента наибольший суб-сегмент и заканчивая $ суммы [J] $, 状态转移方程следующим образом :
    . $$ суммы [J + 1 ] = {начинаются случаи} НУМС [ J + 1] , суммы [J] 0 Lt кр суммы [J] + НУМС [J + 1] другие случаи {конец} $$
  • Две идеи, 53. Максимальная подмассив ответить следующее:
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
класс   { 
общественности : INT maxSubArray ( вектор < INT > & НУМС) { INT SizeofNums = nums.size (); если (SizeofNums == 1 ) { возврата НУМС [ 0 ]; } INT суммы [SizeofNums]; суммы [ 0 ] = НУМС [ 0 ]; для ( Int я = 1 ; г <SizeofNums; я ++) { сумм [I] = [сумм я -1 ] < 0 ? НУМС [I]: суммы [я -1 ] + НУМС [I]; }













INT largestSum = сумма [ 0 ]; для ( INT I = 1 ; г <SizeofNums; я ++) { если (largestSum <суммы [я]) { largestSum = суммы [I]; } } Вернуть largestSum; } };









  • Для того , чтобы получить largestSumпоследовательности , соответствующие переменной , что мы можем startIdxзаписать J-й элемент в конец ( endIdxисходное положение) , а максимальная подсегмент соответствующих суб-последовательностей, $ НУМС [startIdx, ..., endIdx] $ представляет собой соответствующую последовательность; Кроме того, принимая во внимание текущее состояние и предыдущее состояние только соответствующий , он может быть использован вместо переменных массива, сохранить память, избегая при этом получать The largest sum of the whole arrayповторные циклы времени.
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
29
30
31
класс  решений { 
общественности : INT maxSubArray ( вектор < INT > & НУМС) { INT SizeofNums = nums.size (); если (SizeofNums == 1 ) { возврата НУМС [ 0 ]; } // крупная сумма для подмассива заканчивая текущим элементом ИНТ curSum = НУМС [ 0 ]; // крупная сумма подмассива для всего массива INT largestSum = curSum; // подмассив [startIdx, endIdx] с наибольшей суммой для всего массива INT startIdx = 0 , endIdx =










0 ; для ( INT I = 1 ; г <SizeofNums; я ++) { если (курсор < 0 ) { курсор = НУМС [I]; startIdx = я; } Else { курсор скорость + = НУМС [I]; } Если (литниковой> largestSum) { largestSum = скорость; endIdx = я; } } Return largestSum; } };


















152. Максимальный продукт подмассив решения проблем идеи

  • Процесс решения проблем по существу аналогична предыдущему вопросу, но основная проблема должна быть решена заключается в следующем: переходное состояние, то есть, как (макс продукт с J-го элемента является концом суб-сегмента) рассчитывается на основе ответов на суб-проблемы результаты текущей подзадачи.
  • 从上一题的分析可以看出,当前子问题(以第 j 个元素为结尾的子段的max sum)的计算只需考虑上一个子问题的结果 $sum[j-1]$,$sum[j-1] < 0$,因为是加法,显然可以将子问题结果忽略;$sum[j-1] > 0$,$sum[j-1]$ 加上当前元素就是当前子问题的结果。
  • 类似的问题,只不过换成乘积,子问题的求解就变得复杂了,需要考虑以下几种情况:
    • 当前元素是正数,max product可能是正正得正的情况,因为都是整数,乘积>1,上一子问题的结果乘上当前元素即为当前子问题的答案
    • 当前元素是负数,max product可能是负负得正的情况,因此需要维护以第 j 个元素为结尾的子段的min product(很大可能是负数)
    • 另外,需要考虑上一个子问题的结果为0的情况
    • 总之,乘积的最大值为上述三种情况之一
      状态转移方程如下:
      $$ maxProducts[j+1] = max(maxProducts[j-1]*nums[j], minProducts[j-1]*nums[j], nums[j])$$
  • 152. Maximum Product Subarray 解答如下:
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
29
30
class Solution {
public:
int maxProduct(vector<int>& nums) {
int SizeofNums = nums.size();

if(SizeofNums == 1) {
return nums[0];
}
// The largest/least product of subarray ending with the i-th element
int maxProducts[SizeofNums];
int minProducts[SizeofNums];
maxProducts[0] = minProducts[0] = nums[0];
for(int i=1; i<SizeofNums; i++) {
// positive with positive, negative with negative, ignore previous zero
maxProducts[i] = max( max(maxProducts[i-1]*nums[i], minProducts[i-1]*nums[i]), nums[i]);
// positive with negative, negative with positive, ignore previous zero
minProducts[i] = min( min(maxProducts[i-1]*nums[i], minProducts[i-1]*nums[i]), nums[i]);
}

// getting the largest product for the whole array
int largestProduct = maxProducts[0];
for(int i=1; i<SizeofNums; i++) {
if(maxProducts[i] > largestProduct) {
largestProduct = maxProducts[i];
}
}

return largestProduct;
}
};
  • 与上一题类似,添加额外变量,也能实现节省内存,记录子段最大乘积对应子段($nums[startIdx, endIdx]$)的起始和终止位置。
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
class Solution {
public:
int maxProduct(vector<int>& nums) {
int SizeofNums = nums.size();

if(SizeofNums == 1) {
return nums[0];
}
// The largest/least product of subarray ending with the i-th element
int largestProduct = nums[0];
int leastProduct = nums[0];
// The largest product for the whole array
int maxProduct = largestProduct;
// subarray[startIdx, endIdx] with largest product for the whole array
int startIdx = 0, endIdx = 0;
// start index for largestProduct/leastProduct
int startIdx_pos = startIdx, startIdx_neg = startIdx;

for(int i=1; i<SizeofNums; i++) {
int largestProduct_pre = largestProduct;
int leastProduct_pre = leastProduct;

// positive with positive, negative with negative, ignore previous zero
largestProduct = max( max(largestProduct_pre*nums[i], leastProduct_pre*nums[i]), nums[i]);
if((largestProduct_pre != nums[i]) && (largestProduct == nums[i])) {
startIdx_pos = i;
}

// positive with negative, negative with positive, ignore previous zero
leastProduct = min( min(largestProduct_pre*nums[i], leastProduct_pre*nums[i]), nums[i]);
if((leastProduct_pre != nums[i]) && (leastProduct == nums[i])) {
startIdx_neg = i;
}

if(largestProduct > maxProduct) {
maxProduct = largestProduct;
if(largestProduct_pre*nums[i] > leastProduct_pre*nums[i]) {
startIdx = startIdx_pos;
}
else {
startIdx = startIdx_neg;
}
endIdx = я;
}
} Вернуть maxProduct; } };




рекомендация

отwww.cnblogs.com/petewell/p/11408859.html