本文與java語言無關,純粹就是個解決問題的想法
問題:給定一個數組,要求求出數組中連續數和最大的索引對。比如,給定一個數組,裡面有正數有負數和0。其中肯定有一個連續的序列(連續的,中間不能間斷),比如說是索引3到索引5,這個序列的和是這個數組中連續序列中最大的,別的都沒這個大。
{0,2.-1,9,7.6,-8,16},這個數組中就是索引三到索引五這個連續序列的和最大。要求演算法的時間複雜度問O(n)。
問題解決:如果時間複雜度要求是O(n³)或者是O(n平方),就沒意思了,直接迴圈搞定。
O(n)的時間複雜度如何解決:
注意,因為整個數組可能都是負數,這時候問題就退化成尋找數列中最大的負數了。首先,針對這種情況進行處理,將數組進行一次迴圈,找出第一個非負數索引和最後一個非負數索引,這個可以在一次迴圈中完成,如果 1)沒找到,說明數組中全是負數,澤跳出迴圈,進行下一輪迴圈,尋找最大負數 2)如果兩者相等,說明數組中只有一個正數,直接返回索引對 3)如果兩者不等,則是相對複雜的情況,下面進行處理,到現在位置,時間複雜度是O(n),因為之迴圈了一次。
1:將數組的第一個非負索引和最後一個非負索引之間的連續的正數和連續的負數相加。比如{0,2.-1,9,7.6,-8,16},處理完後就應該得到數組{2, -1, 22, -8, 16}。這樣整個數組就肯定是一個正負相間的數組。而且開頭和結尾肯定是非負數。在進行處理的時候,還要維護一個大小是結果兩倍的數組,用來儲存每個元素的原來序列數值,比如,對於上面的數組,這個序列數組就應該是{0,1,2,2,3,5,6,6,7},這個數組是數組index,其中0,1是第一個元素在原來數組中的序列,2,2 是第二個元素在原來數組中的序列,3,5是第三個元素在原數組中的序列,依此類推。本步驟的時間複雜度也是O(n),沒有迴圈嵌套,空間複雜度是O(2n)
2:現在得到一個正負相間的數組,而且數組中開頭結尾都是非負數,而且數組中沒個元素在原始數組中的索引序列對都是知道的。然後:
int start = 0;
int end = 0;
int count = 0;
對這個數組進行一次迴圈,迴圈中:
count += 數組[i]
if(count > 0){
將count的索引對(start, end)放入數組A中
將count的數值放入數組B中
} else{
count = 0;
}
這個迴圈時間複雜度是O(n),空間複雜度O(2n)
迴圈結束後,要的結果就在數組A和數組B中,遍曆數組B找到最大的元素,然後根據最大元素的索引去A中找出索引對,然後根據這個索引對去前面的數組index找出結果。時間複雜度O(n)
整個演算法看下來,時間複雜度就是O(n),進行了4次O(n)的迴圈,空間複雜度比較大一些,最大可能需要原來數組大小五倍的儲存空間才能完成整個計算。