3.求子數組的最大和(數組)
題目:
輸入一個整形數組,數組裏有正數也有負數。
數組中連續的一個或多個整數組成一個子數組,每個子數組都有一個和。
求所有子數組的和的最大值。要求時間複雜度爲O(n)。
例如輸入的數組爲1, -2, 3, 10, -4, 7, 2, -5,和最大的子數組爲3, 10, -4, 7, 2,
因此輸出爲該子數組的和18。
#include <iostream>
class Array
{
public:
Array(int a[],int length):m_array(a),m_length(length) {}
void Findbest();
void Print();
private:
int *m_array;
int m_left;
int m_right;
int m_length;
int m_nearLeft;
int m_nearRight;
int m_max;
int m_nearMax;
};
void Array::Findbest()
{
m_left = 0;
m_right = -1;
m_nearLeft = 0;
m_nearRight = -1;
m_max = m_nearMax = 0 ;
for (int i = 0 ; i < m_length ; i++ )
{
if ( m_array[i] >= 0 ) {
if ( m_nearRight + 1 == i ) {
m_nearMax += m_array[i] ;
m_nearRight = i ;
}
else {
m_nearLeft = m_nearRight = i;
m_nearMax = m_array[i] ;
} // else if ( m_nearRight +1 == i )
if (m_right + 1 == i) {
m_right = i;
m_max += m_array[i];
}
else {
if ( m_max < m_nearMax ) {
m_max = m_nearMax ;
m_left = m_nearLeft ;
m_right = m_nearRight ;
}
} //else if (m_right +1 == i)
} //end if ( m_array[i] >= 0 )
else {
if ( m_nearRight + 1 == i && m_nearMax + m_array[i] > 0 ) {
m_nearMax += m_array[i] ;
m_nearRight = i ;
}
else {
m_nearLeft = m_nearRight = 0;
}
}
} //end of for
}
void Array::Print()
{
std::cout<<"left="<<m_left+1<<" right="<<m_right+1<<std::endl;
std::cout<<"Total is "<<m_max<<std::endl;
for(int i = m_left ; i <=m_right ; i++ ) {
std::cout<<m_array[i]<<" ";
}
std::cout<<std::endl;
}
int main()
{
int t[]={-1,-2,3,10,-4,7,2,-5};
Array a(t,8);
a.Findbest();
a.Print();
getchar();
return 0;
}
利用動態規劃的思想:
當前a[i]的最大子數組等於 a[i-1]的最大子數組 + a[i] a[i]>=0 a[i-1]的最大子數組右值下標爲i-1
max (a[i-1]的最大子數組 or a[i]最靠近右邊大於零的子數組) a[i]>=0 a[i-1]的最大子數組右值下標不爲i-1
當 a[i] <0 時 僅需要對 a[i]最靠近右邊大於零的子數組 進行處理即可:
當 a[i-1]最靠近右邊大於零的子數組 + a[i] >= 0 時 子數組增加
否則對子數組清空
上面的思路比較複雜 下面的判斷簡化,只需要用最近的記錄的和和以前的最大值比較,如果記錄的最近的和小於0,則重新記錄
#include <iostream>
class Array
{
public:
Array(int a[],int length):m_array(a),m_length(length) {}
void Findbest();
void Print();
private:
int *m_array;
int m_left;
int m_right;
int m_length;
int m_nearLeft;
int m_nearRight;
int m_max;
int m_nearMax;
};
void Array::Findbest()
{
m_left = 0;
m_right = -1;
m_nearLeft = 0;
m_nearRight = -1;
m_max = m_nearMax = 0 ;
for (int i = 0 ; i < m_length ; i++ )
{
m_nearMax += m_array[i];
m_nearRight++;
if (m_nearMax > 0)
{
if ( m_nearMax > m_max)
{
m_max = m_nearMax;
m_left = m_nearLeft;
m_right = m_nearRight;
}
}
else
{
m_nearMax = 0;
m_nearLeft = i + 1 ;
m_nearRight = i;
}
} //end of for
}
void Array::Print()
{
std::cout<<"left="<<m_left+1<<" right="<<m_right+1<<std::endl;
std::cout<<"Total is "<<m_max<<std::endl;
for(int i = m_left ; i <=m_right ; i++ ) {
std::cout<<m_array[i]<<" ";
}
std::cout<<std::endl;
}
int main()
{
int t[]={-1,-2,3,10,-4,7,2,-5};
Array a(t,8);
a.Findbest();
a.Print();
getchar();
return 0;
}