1. 程式人生 > >動態規劃演算法(連續子陣列最大和,O(N)時間複雜度O(1)空間複雜度) 【更新於:2018-05-13】

動態規劃演算法(連續子陣列最大和,O(N)時間複雜度O(1)空間複雜度) 【更新於:2018-05-13】

這個題目最早在13年阿里筆試出現,直到前兩天面試另一家電商又出現,哎,欠的都是要還的。

這個問題的思路如下:一維陣列的下標連續的元素構成連續子陣列,求所有連續子陣列中和最大的那個子陣列。

解析:2018-11-08

1 首先這個問題要轉化為Q(n)的問題,對於Q(n)的問題要轉化成Q(n) = Q(n-1) + An的問題。

2 只要能意識到這一點,其實就可以有希望在O(n)的時間內解決,不然,那就複雜的無法解決(因為你無法通過普通的迴圈遍歷來做到,就算做到了,那複雜性也是難以承受的)。

3 上面的思想本質上還是一維動態規劃演算法。按照地歸解分類討論一下即可。

思路一旦確定,解的時候只需要更新各個臨時變數和下標即可

解釋(如上圖所示):

1 Q(n)表示元素為n的陣列其最優解(其下標範圍為[i, j))

2 元素n+1為陣列的第n+1個元素(其下標範圍為n1)

3 A2為Q(n)產生時的一個子序列,這個序列的是Q(n)右側和n+1之間的所有元素構成的集合,該序列的和一定是負值(下標範圍為[j, n1))

4 A1為Q(n)產生時的Q(n)左側的序列,該序列的和一定是負值

5 A1無需考慮,我們主要考慮加入第n+1元素時,新的Q(n+1)可能是那種情況即可。這裡可能情況有四種。屬於列舉法解決問題。

6 首先考慮新的序列Q(n+1)會不會變的更長,也就是A2+(n+1)會不會也加入進來,這個是我們的直覺。這個時候會不會加進來主要看這個序列的和是不是大於零。也就是A2 + (n+1) > 0 ?  大於零也不是就一定要加上Q(n)。因為Q(n)可能是個負數,加了只會更小,這時候就不能加入,而A2又是和為負數,所以新的Q(n+1)只能是第n+1這個元素自己。這裡的討論只是以其中的一種情況為例討論的。其餘三種情況類似,參考上圖即可。

7 本題的難點就在於列舉出各種情況,很容易考慮不周,我就見過有人寫的程式碼過於簡單,考慮不周的。而且也寫出來,這個是誤人子弟(當然讀者自己要去驗證和辨別)

8 本題的第二個難點在於標記變數的設定和在各種情況下的更新。如果你把上圖先畫出來,對著圖寫程式,還是很簡單的(即便這樣,我的A2更新還是出過問題,改了兩次才改好)。一定要嚴格定義上圖中各個集合的範圍,這時候他們在各種情況下的更新時機才會比較清晰,程式碼才不會寫BUG。

程式碼:

#include <cassert>
#include <iostream>
#include <vector>
using namespace std;

int MaxSumOfContinuousSubSequence(const vector<int>& a, int& i, int& j)
{
	if (a.size() == 0)
	{
		throw "sequence must has one element at least!";
	}

	if (a.size() == 1)
	{
		return a[0];
	}
	//各個集合及其下標範圍
	//Q(n)[i,j) 上一次的最優解與下標範圍
	//A2[j,n1)  上一次的最優解與當前第n+1個元素之間的序列(A2各元素和總是負值)
	//n1[n+1,n+2)  當前Q(n+1)比Q(n)多出來的那個新元素
	i = 0;//Q(n)的起始下標
	j = 1;//A2的起始下標
	int n1 = 1;//n1的起始下標

	int currentMaxSum = a[0];
	int sumA2 = 0;

	for (n1 = 1; n1 < a.size(); ++n1)
	{
		if (sumA2 + a[n1] >= 0)
		{
			if (currentMaxSum > 0)
			{
				currentMaxSum = currentMaxSum + sumA2 + a[n1];
				sumA2 = 0;
				j = n1 + 1;
			}
			else
			{
				currentMaxSum = a[n1];
				sumA2 = 0;
				i = n1;
				j = n1 + 1;
			}
		} 
		else
		{
			if (currentMaxSum > a[n1])
			{
				currentMaxSum = currentMaxSum;
				sumA2 = sumA2 + a[n1];
			}
			else
			{
				currentMaxSum = a[n1];
				sumA2 = 0;
				i = n1;
				j = n1 + 1;
			}
		}
	}

	return currentMaxSum;
}

void test_max_sub_sum(const vector<int>& a)
{
	cout << "sequence ";
	for each (auto var in a)
	{
		cout << var << " ";
	}
	cout << endl;
	int begin, end;
	cout << "MaxSumOfContinuousSubSequence " << MaxSumOfContinuousSubSequence(a, begin, end) << endl;
	for (int i = begin; i < end; ++i)
	{
		cout << a[i] << " ";
	}
	cout << endl<<endl;
}

int main()
{
	vector<int>  a1 = { -1, 100, -200, 13};
	test_max_sub_sum(a1);

	vector<int>  a2 = { -1, 100, -200, 201};
	test_max_sub_sum(a2);

	vector<int>  a3 = { -1, 100, -200, 201, -20, -20, -20, 61};
	test_max_sub_sum(a3);

	vector<int>  a4 = { -1, 100, -200, 201, -20, -20, -20, 61, -104, 103};
	test_max_sub_sum(a4);

	vector<int>  a5 = { -1, 100, -200, 201, -20, -20, -20, 61, -104, 103, 1};
	test_max_sub_sum(a5);

	return 0;
}

輸出:

相關推薦

動態規劃演算法連續陣列O(N)時間複雜O(1)空間複雜 更新2018-05-13

這個題目最早在13年阿里筆試出現,直到前兩天面試另一家電商又出現,哎,欠的都是要還的。 這個問題的思路如下:一維陣列的下標連續的元素構成連續子陣列,求所有連續子陣列中和最大的那個子陣列。 解析:2018-11-08 1 首先這個問題要轉化為Q(n)的問題,對於Q(n)的

連續陣列O(n兩種解法雙指標 動態規劃

題目描述 HZ偶爾會拿些專業問題來忽悠那些非計算機專業的同學。今天測試組開完會後,他又發話了:在古老的一維模式識別中,常常需要計算連續子向量的最大和,當向量全為正數的時候,問題很好解決。但是,如果向量中包含負數,是否應該包含某個負數,並期望旁邊的正數會彌補它呢?例如:{6,-3,-2,7

動態規劃--求目標值問題、找零錢問題以及求連續陣列 --java

1、動態規劃一般可分為線性動規,區域動規,樹形動規,揹包動規四類。 舉例: 線性動規:攔截導彈,合唱隊形,挖地雷,建學校,劍客決鬥等; 區域動規:石子合併, 加分二叉樹,統計單詞個數,炮兵佈陣等; 樹形動規:貪吃的九頭龍,二分查詢樹,聚會的歡樂,數字三角形等;

常見演算法 - 連續陣列

public class Solution { public int FindGreatestSumOfSubArray(int[] array) { if(array.length == 0){ return 0; }

求某個數組裡連續陣列的幾個演算法

注意:這裡的陣列元素,有可能全為負。這樣,所謂的: int find_max_array(const vector<int> &a) { int max_sum = 0; int this_sum = 0; fo

劍指offer:(31時間效率 :連續陣列

package jianzhioffer; public class Solution31 { //動態規劃:就是將中間值儲存下來 public static int FindGreatestSumOfSubArray(int[] array) { if (array == null

劍指offer連續陣列

題目:在古老的一維模式識別中,常常需要計算連續子向量的最大和,當向量全為正數的時候,問題很好解決。但是,如果向量中包含負數,是否應該包含某個負數,並期望旁邊的正數會彌補它呢?例如:{6,-3,-2,7,-15,1,2,2},連續子向量的最大和為8(從第0個開始,到第3個為止)。給一個數組,返回它的最大連續子序

牛客網 《劍指Offer》程式設計 30.連續陣列

題目描述 HZ偶爾會拿些專業問題來忽悠那些非計算機專業的同學。今天測試組開完會後,他又發話了:在古老的一維模式識別中,常常需要計算連續子向量的最大和,當向量全為正數的時候,問題很好解決。但是,如果向量中包含負數,是否應該包含某個負數,並期望旁邊的正數會彌補它呢?例如:{6,

陣列連續陣列乘積

題目:給定一個數組,要求其連續子陣列的最大和。如陣列為{6,-3,-2,7,-15,1,2,2},連續子陣列的最大和為8(從第0個開始,到第3個為止) 解法1:首先最容易想到的便是利用列舉的方法,枚舉出所有可能大小的連續子陣列的和,然後選出其中最大的一個。即從連續子陣列的大

連續陣列

題目描述: 輸入一個整形陣列,數組裡有正數也有負數。 陣列中連續的一個或多個整陣列成一個子陣列,每個子陣列都有一個和。 求所有子陣列的和的最大值。要求時間複雜度為O(n)。 例如輸入的陣列為1, -2, 3, 10, -4, 7, 2, -5,和最大的子陣列為3, 10,

連續陣列問題

1. 問題描述 輸入一個整形陣列,求陣列中連續的子陣列使其和最大。比如,陣列x 應該返回 x[2..6]的和187. 2. 問題解決 我們很自然地能想到窮舉的辦法,窮舉所有的子陣列的之和,找出最大值。 窮舉法 i, j的for迴圈表示x[i..j],k的for

python實現求連續陣列

問題描述:例如:[6,-3,-2,7,-15,1,2,2]求連續子陣列中的最大和,此陣列中最大和為8,從arr[0]到arr[3]。其餘位置都比這個要小。最大連續子陣列的特點:(1)第一個不為負數(2)如果前面數的累加加上當前數小於當前數,說明這次累加對總體的結果是無效的;如

動態規劃典型例題--連續陣列

題目描述:給定一個數組arr,陣列中的元素有整數也有負數,陣列中的一個或者連續多個數組成一個子陣列。 求所有子數組裡面的最大和。例如現在有陣列 {1 , -2 , 3 , 10 , -4 , 7 ,

動態規劃問題系列---連續陣列(二維)的

題目1 一維陣列的連續子陣列的最大和 輸入一個整型陣列,數組裡有正數也有負數。陣列中一個或連續的多個整陣列成一個子陣列。求所有子陣列的和的最大值。要求時間負責度為O(n)。 分析 假如輸入陣列為{1,-2,3,10,-4,7,2,-5},我們嘗試從頭

Maximum Subarray連續序列 -- LeetCode經典動態規劃

原題連結: http://oj.leetcode.com/problems/maximum-subarray/這是一道非常經典的動態規劃的題目,用到的思路我們在別的動態規劃題目中也很常用,以後我們稱為”區域性最優和全域性最優解法“。基本思路是這樣的,在每一步,我們維護兩個變數,一個是全域性最優,就是到當前元

演算法陣列陣列的解決方法詳解

題目: 輸入一個整形陣列,數組裡有正數也有負數。 陣列中連續的一個或多個整陣列成一個子陣列,每個子陣列都有一個和。 求所有子陣列的和的最大值。 例如輸入的陣列為1, -2, 3, 10, -4, 7, 2, -5,和最大的子陣列為3, 10, -4, 7, 2, 因此

動態規劃——連續序列

題目描述: 輸入一個整型陣列,數組裡有正數也有負數。 陣列中連續的一個或多個整陣列成一個子陣列,每個子陣列都有一個和。 求所有子陣列的和的最大值。要求時間複雜度為O(n)。 例如輸入的陣列為1,

六種姿勢拿下連續序列問題附虛擬碼以HDU 1003 1231為例

問題描述:       連續子序列最大和,其實就是求一個序列中連續的子序列中元素和最大的那個。       比如例如給定序列:            { -2, 11, -4, 13, -5, -2 }         其最大連續子序列為{ 11, -4, 13 },最大和

迴圈陣列陣列

一。實驗要求 1.輸入一個整型陣列,數組裡有正數也有負數,陣列中一個或多個整陣列成一個整陣列,每個子陣列都有一個和。 2.陣列可以首位相連,允許A【i-1】,....,A[n-2],A[0]........A[j-1]和最大 3.返回最大子陣列的位置,求最大子陣列的和. 二、實驗思路 迴圈陣列,也就

連續序列問題---python實現

連續子序列最大和問題—python實現 問題:連續子序列最大和 給定一個數字序列[A1A2A3…An],求i,j(1<=i<=j<=n)使得Ai…Aj和最大, 輸出這個最大和(連續大子序列最大和) 例如: 輸入: L=[-2 ,6,