2014-10-09 81 views
0

在給定數組中查找帶有不同數字的最大連續子數組和。如果在任何子陣列中存在至少兩個相等的數字,則該數字的值等於0.查找不同數字的最大連續子數組求和

所有數字都是正數。

我寫了O(n²)蠻力算法,但它肯定太慢了。 我試圖用Kadane的算法來混合它,但似乎並不奏效。

+0

你試過對數組進行排序並插入所有不同的數字嗎? O(n * log(n))用於排序+ O(n)用於插入 – CIsForCookies 2014-10-09 18:41:35

+0

@CIsForCoocckies它是不正確的。對於數組5,2,2,4來說,選擇整個數組是最理想的,儘管並非所有的數字都是不同的。 – kraskevich 2014-10-09 18:43:00

+0

我想我不明白這個問題。如果subArray是5,2,2,4,它的總和是(5 + 4 = 9),而不是取(5,4,2)總和爲11,那麼爲什麼要整個數組呢? – CIsForCookies 2014-10-09 18:48:34

回答

1

使用分段樹可以獲得時間複雜度O(n log n)

  1. 讓我們假設答案的左邊框(我們稱之爲L)是固定的。從左邊的所有東西都可以忽略。數組其餘部分的每個元素可以表示爲:
    a)+x如果它是第一次出現x
    b)-x如果它是第二次出現x
    c)0如果它是第三次(或更晚)發生的x,
    其中x = a[i]
    然後答案是所有子陣列的最大子陣列總數[L, R]其中R >= L

  2. 那麼如何有效實施?最初,爲[0, n - 1]範圍構建分段樹。段樹中的每個葉子都包含前綴總和,該總和始於L,並以此葉子結尾(到目前爲止爲0)。填寫它爲L = 0(通過遍歷整個陣列,並添加+x-x適當的足夠的分段樹)。這些部分在O(n log n)中工作。還有一種觀察:當L增加時,該值僅在最多3個位置上變化(因爲a[L]的第一次出現現在處於另一個位置,但其他數字沒有變化)。分段樹中的每個更新爲O(log n),因此需要O(log n)時間來增加L一次。總時間複雜度爲O(n log n),因爲L遞增O(n)次。不要忘記查詢分段樹,以獲得每個L的最大值,並選擇最大的值作爲答案。

因此,所有你需要的是一個支持兩種操作的段樹:添加相同數量的所有元素在給定的範圍內,並得到所有元素中最高。這是一個衆所周知的問題,並不是很難實施。

+0

嗯,我想你是對的!但我仍然不明白我應該如何增加L,你能解釋我嗎?謝謝! – 2014-10-09 19:45:40

+0

我們來看看數字a [L]。當L遞增時,它的第一個和第二個位置向右移動。所以+α[L]和-a [L]現在位於其他位置和段樹應appropriatly更新(如果您存儲給定數字的位置,你可以找到新的位置快速使用二進制搜索或通過移動指針當你移動L)。 – kraskevich 2014-10-09 19:50:06