這個題目在動態規劃的部分,這裏明顯用到了。
我們知道,可以使用動態規劃思想的問題的兩個重要特征是最優子結構和重疊子問題。我們來分析壹下這個問題:
對於具有n個元素的序列nums,設最長的單調遞增子序列為Sm(n)(m是遞增子序列的長度),則Sm有兩種情況:
1.如果nums【n】大於Sm-1的最後壹個元素,則Sm由Sm-1加上nums【n】組成。
2.如果nums【n】小於或等於Sm-1的最後壹個元素,則Sm為Sm-1。
但是,這種考慮有問題,因為如果有多個Sm-1序列,我們應該用nums【n】檢查每個序列。如果nums【n】小於等於Sm-1的所有尾元素,並且Sm-2中存在尾元素小於nums【n】的序列,我們應該如何選擇,Sm應該是多少?
Sm-1+nums【n】、Sm-1、Sm-2+nums【n】
因此,前面的分析是有問題的。在長度相同的情況下,我們更喜歡包含nums【n】的序列為Sm(n),因為每個新添加的元素都可能改變不同長度的增量子序列,因此我們需要維護每個增量子序列以獲得最佳。
這裏的最佳子結構是n個元素的最長遞增子序列是從前面的n-1個元素或加上nums【n】結束的遞增子序列之壹,這自然有許多重疊子序列。
代碼如下:
/************************************************************************/
/*算法15.4-5簡介
*在n個數的序列中找出最長的單調遞增子序列。
*利用動態規劃的思想,時間復雜度為O(N2)*/
/************************************************************************/
# include & ltiostream & gt
使用命名空間std
void print sequence(int * b,int* nums,int last);
int main()
{
int n = 8;
int nums【9】= { 0,1,7,8,9,2,3,4,5 };
//b在當前元素所在的增量子序列中存儲當前元素的上壹個元素序列號。
//c存儲以當前元素結束的遞增子序列長度。
//last存儲序列中最長遞增子序列的最後壹個元素的序列號,直到當前元素。
//maxLen存儲當前最長增量子序列的長度。
int b【9】= { 0 },c【9】= { 0 },last【9】= { 0 },maxLen = 0;
c【1】= 1,last【1】= 1;
for(int I = 1;我& lt= n;i++)
{
for(int j = 1;j & lt我;j++)
{
if(nums【j】& lt;nums【I】& amp;& ampc【j】+1》c【I】)
{
c【I】= c【j】+1;
b【I】= j;
last【I】= I;
maxLen = c【I】;
} else if(c【j】》;c【I】){
maxLen = c【j】;
last【I】= last【j】;
}
}
}
cout & lt& lt“原始序列長度為“
for(int I = 1;我& lt= n;i++)
{
cout & lt& ltnums【I】& lt;& lt" ";
}
cout & lt& ltendl & lt& lt“最長遞增子序列長度為“
print sequence(b,nums,last【n】);
cout & lt& ltendl
返回0;
}
void打印序列(int *b,int* nums,int last)
{
if(b【last】》;0)
print sequence(b,nums,b【last】);
cout & lt& ltnums【last】& lt;& lt" ";
}