【牛客網刷題】一次難忘的程式設計教訓
昨天刷這樣一道程式設計題:
--------------------------------------------------------------------------------------------------
求連續子陣列的最大和。
一個非空整數陣列,選擇其中的兩個位置,使得兩個位置之間的數和最大。 如果最大的和為正數,則輸出這個數;如果最大的和為負數或0,則輸出0--------------------------------------------------------------------------------------------------
看到題目後,我的第一反應:“可以根據積分原理來解決,先將陣列從左到右進行累加,根據累加陣列的最小值、最大值來計算連續子陣列的最大和”。
想象中,累加陣列的折線圖大約是這個樣子:
“很顯然,連續子陣列和的最大值為:累加陣列的最大值與最小值之差。”
“如果累加陣列的全域性最大值在最小值左邊怎麼辦?”
“那就找它的區域性最大值、最小值,再比較多個區域性的結果,取最大值。”
“如何找區域性最大值、最小值?”
“把累加陣列切分為兩部分,迭代計算。”
頭腦裡這麼想著,手指頭也跟著活動起來了,反正這就和“累加陣列”槓上了。
寫完後提交程式碼試執行,部分case不通過。然後修修補補,終於提交通過了。
程式碼如下:
def find_max_sublist_sum(a_list): # 空list直接返回結果0 if len(a_list) == 0: return 0 # 去除list前面連續的負整數,生成新的new_list;如果list全部元素為負,則返回結果0 indx = 0 for x in a_list: if x > 0: break else: indx += 1 if indx < len(a_list): new_list = a_list[indx:] else: return 0 # 從前往後,計算new_list元素的累積和,生成accumulate_list accumulate = 0 accumulate_list = [] for x in new_list: accumulate += x accumulate_list.append(accumulate) # 找出累積和列表最大值、最小值對應的index index_min = accumulate_list.index(min(accumulate_list)) index_max = accumulate_list.index(max(accumulate_list)) # 根據累積和列表的最大值、最小值位置進行分類計算 if index_min < index_max: # 最小值在最大值左邊,取最小值到最大值區間內增量 return max(accumulate_list) - min(min(accumulate_list), 0) elif index_min == index_max == 0: # 最小值、最大值均 index == 1,說明列表只有一個正數 return accumulate_list[0] else: # 將列表分成2部分,遞迴處理 list1 = new_list[:index_max+1] list2 = new_list[index_max+1:] return max(find_max_sublist_sum(list1), find_max_sublist_sum(list2)) if __name__ == '__main__': import sys for line in sys.stdin: testlist = line.split(',') testlist = [int(testlist[i]) for i in range(len(testlist))] print(find_max_sublist_sum(testlist))
自我感覺,這個解法有些複雜,但是也沒認真去想其他的辦法。
今天再回過來看時,看到@牛客692333551號貼出來的解法,我恍然大悟。
@牛客692333551號解法如下:
x = [int(i) for i in input().split(',')] res = 0 d = max(0, x[0]) res = max(res, d) for i in range(1, len(x)): d = max(d + x[i], 0) res = max(res, d) print(res)
原來自己的方法太蠢、太醜了!不忍直視!
為什麼自己如此堅決地捍衛自己的“第一反應”,寧可絞盡腦汁去修修補補,也不願去換個思路去想?
第一反應是自己的直覺,直覺一般憑藉經驗做出反應,卻不一定靠譜,特別是那些經驗不足者的直覺。
對於彈出的直覺反應,我們應該用理性思維去進行判斷。
我們不要太懶惰了,任由著直覺去亂來,最後還得去幫它填坑。
參考:
https://www.nowcoder.com/questionTerminal/459bd355da1549fa8a49e350bf3df484