題目描述:
給定一個長度為N的數組,找出一個最長的單調自增子序列(不一定連續,但是順序不能亂)
例如:給定一個長度為8的數組A{1,3,5,2,4,6,7,8},
則其最長的單調遞增子序列為{1,2,4,6,7,8},長度為6。
輸入描述:
第一行包含一個整數T,代表測試資料群組數。
對於每組測試資料: N-數組的長度
a1 a2 … an (需要計算的數組)
保證: 1<=N<=3000,0<=ai<=MAX_INT.
輸出描述:
對於每組資料,輸出一個整數,代表最長遞增子序列的長度。
輸入例子:
2
7
89 256 78 1 46 78 8
5
6 4 8 2 17
輸出例子:
3
3
分析:這道題說實話也困擾了我兩天,今天晚上才想明白的,具體實現其實很簡單,就是迴圈內嵌迴圈這個比較的意思在裡面。很多人說到了動態規劃,很抱歉,鄙人能力有限,對於動態規劃來說,我覺得是設定個臨時變數來決定繼續不繼續某幾句程式而已。對於這道題我分兩部分來說下:
第一部分,就是所謂的對一個無序序列來求它的最長遞增子序列。具體實現是通過三層迴圈依次遍曆,得到最終想要的結果,解析和實現代碼如下:
#-*-coding:UTF-8-*-def CalMaxLen(Objlist): b = []#b是用來存放每一次遍曆或者說選擇好的遞增序列的長度的 for i in range(len(Objlist)): #print 'when i =%d:' % i #max = Objlist[i] for j in range(i+1,len(Objlist)): print 'when i= %d,from %dth ele:' % (i,j) #當第i次迴圈,也就是說下標為i的元素作為我們要找的 #遞增序列的第一個,這個時候呢,我們就開始從i後面的 #元素開始遍曆了, k = j #請注意k是什麼呢。就是一個標記器,當第i次迴圈 #也就是說下標為i的元素為遞增序列第一個元素時 #我們依次要選擇從i+1、i+2、i+3…i+len(objlist)開始 #因為遞增序列中的元素在原序列中可以不連續,但必須滿足 #遞增。 a = [] #a用來存放每一次最基本的迴圈後的遞增序列 #比如i=0,j=1時我們找到的遞增序列 max = Objlist[i] #我們每次把開始元素設定成最大,這樣進行選擇 a.append(Objlist[i])#先把起始元素加進遞增表裡 for m in range(k,len(Objlist)): if Objlist[m] >= max: max = Objlist[m] a.append(Objlist[m]) #如果從下標為j的元素後算起。大於max的就更新max else: continue # 小於的話那就繼續找,continue print 'the addly list is', a #輸出此次迴圈後得到的遞增序列 b.append(len(a)) #然後把這個遞增序列的長度放到最終各個迴圈次數下的 # 遞增序列長度表中 if i == len(Objlist)-1: a = [] a.append(Objlist[i]) print 'when i is the last ele:' print 'the addly list is only:',a #這裡要注意,當i等於最後一個元素的下標時 #上面的j就取不到了,這個時候那我們就列印最後一個元素 #因為它必然就是一個單元素 c = b[0] for i in range(len(b)): if c <= b[i]: c = b[i] return cs = map(int,raw_input().split())d = CalMaxLen(s)print 'So, the Max length of the addly list in the objective list is: ',d
E:\Python27\python.exe D:/python/python演算法/b.py
1 5 2 4
when i= 0,from 1th ele:
the addly list is [1, 5]
when i= 0,from 2th ele:
the addly list is [1, 2, 4]
when i= 0,from 3th ele:
the addly list is [1, 4]
when i= 1,from 2th ele:
the addly list is [5]
when i= 1,from 3th ele:
the addly list is [5]
when i= 2,from 3th ele:
the addly list is [2, 4]
when i is the last ele:
the addly list is only: [4]
So, the Max length of the addly list in the objective list is: 3
Process finished with exit code 0
上面就是這個問題最核心處理過程的解決方案
接下來第二部分,就是針對這道題目的輸入來做個輸出了,當然我會把不必要的輸出給注釋掉:
#-*-coding:UTF-8-*-def CalMaxLen(Objlist): b = []#b是用來存放每一次遍曆或者說選擇好的遞增序列的長度的 for i in range(len(Objlist)): #print 'when i =%d:' % i #max = Objlist[i] for j in range(i+1,len(Objlist)): #print 'when i= %d,from %dth ele:' % (i,j) #當第i次迴圈,也就是說下標為i的元素作為我們要找的 #遞增序列的第一個,這個時候呢,我們就開始從i後面的 #元素開始遍曆了, k = j #請注意k是什麼呢。就是一個標記器,當第i次迴圈 #也就是說下標為i的元素為遞增序列第一個元素時 #我們依次要選擇從i+1、i+2、i+3…i+len(objlist)開始 #因為遞增序列中的元素在原序列中可以不連續,但必須滿足 #遞增。 a = [] #a用來存放每一次最基本的迴圈後的遞增序列 #比如i=0,j=1時我們找到的遞增序列 max = Objlist[i] #我們每次把開始元素設定成最大,這樣進行選擇 a.append(Objlist[i])#先把起始元素加進遞增表裡 for m in range(k,len(Objlist)): if Objlist[m] >= max: max = Objlist[m] a.append(Objlist[m]) #如果從下標為j的元素後算起。大於max的就更新max else: continue # 小於的話那就繼續找,continue #print 'the addly list is', a #輸出此次迴圈後得到的遞增序列 b.append(len(a)) #然後把這個遞增序列的長度放到最終各個迴圈次數下的 # 遞增序列長度表中 if i == len(Objlist)-1: a = [] a.append(Objlist[i]) #print 'when i is the last ele:' #print 'the addly list is only:',a #這裡要注意,當i等於最後一個元素的下標時 #上面的j就取不到了,這個時候那我們就列印最後一個元素 #因為它必然就是一個單元素 c = b[0] for i in range(len(b)): if c <= b[i]: c = b[i] return cn = int(raw_input())#n是輸入的組數endlist = []for i in range(n): r = int(raw_input()) s = map(int, raw_input().split()) endlist.append(CalMaxLen(s))for i in endlist: print i
輸出樣本:
E:\Python27\python.exe D:/python/python演算法/MaxAddlyList.py
2
7
89 256 78 1 46 78 8
5
6 4 8 2 17
3
3
Process finished with exit code 0
OK!收工。
總結一下就是:思路要清晰,至於說這個程式是否還要怎麼最佳化,希望大神來指點。