LeetCode 805 陣列

Mondo 科技 更新 2024-02-06

給定乙個整數陣列 a,我們希望將 A 陣列中的每個元素移動到 b 或 c 陣列。 (b 和 c 陣列在開頭都是空的)。

當且僅當我們完成了這樣的移動時,才返回 true,因此 B 陣列的平均值和 C 陣列的平均值相等,並且 B 陣列和 C 陣列都不是空的。

示例: 輸入:

輸出:true

解釋:我們可以將陣列分為 [1,4,5,8] 和 [2,3,6,7],它們的平均值都是 45。

注意:a-array 的長度範圍為 [1, 30]。

a[i] 的資料範圍為 [0, 10000]。

回顧性實際分離列表 b 和 c 的平均值等於列表 a 的平均值,這是這個問題的起點。 證據如下:

設 b 的長度為 k,a 的長度為 n。 是的sum(b)/k = sum(c)/(n-k)

然後:

sum(b) *n - k) = sum(c) *ksum(b) *n = (sum(b) +sum(c)) ksum(b) / k = (sum(b) +sum(c)) / nsum(b) / k = sum(a) / n
因此,我們可以列舉所有 a 的大小 i,因此 b 的大小為 n - i,其中 n 是陣列 a 的大小。

由於列表 b 和 c 的平均值等於列表 a 的平均值。因此,我們可以提前計算出 a 的平均值 **g,那麼 a 的總和實際上是 i * g,我們使用回溯來求 i * g 之和的組合,我們可以返回 true,否則返回 false。

值得注意的是,我們只需要列舉 1 到 n2 範圍內的 i,就可以達到修剪的效果。

核心**:

def splitarraysame**erage(self, a: list[int]) bool: n = len(a) *g = sum(a) / n for i in range(1, n // 2 + 1): for combination in combinations(a, i): if abs(sum(combination) -g * i) <1e-6: return true return false
上圖**由於回溯與 sum 巢狀,因此時間複雜度為回溯的時間複雜度 * 和的時間複雜度,因此在最壞的情況下,總時間複雜度為 $n * 2 n$。 替換問題的 n 範圍是 30,一般這種複雜度只能解決 20 以下的問題,因此需要考慮優化。

我們可以直接計算它們,而不是將所有組合相加all 和,則該演算法的時間複雜度為 $2 n$。

核心**:

def splitarraysame**erage(self, a: list[int]) bool: n = len(a) *g = sum(a) / n for i in range(1, n // 2 + 1): for s in combinationsum(a, i): if abs(s - g * i) <1e-6: return true return false
不幸的是,這仍然不足以通過所有測試用例。

接下來,我們可以通過進一步修剪的方式達到AC的目的。 好多回溯這些問題都是基於修剪的。 修剪是回溯問題的核心測試點。

這個招數是雙向搜尋,雙向搜尋可以將指數數從 $o(2 n)$ 減少到 $o(2 (n 2))$ 進入問題,使指數變為 30 2 = 15,並且可以通過。

具體來說,我們可以將組合總和的一半變成陣列(你可以稱之為 a1),然後我們可以將組合總和的一半變成陣列(你可能會認為呼叫 a2),那麼 a1 和 a2 的總和不是 **g * i 嗎? 為簡單起見,我們可以將 a1 設定為陣列 a 的前半部分,將 a2 設定為陣列的後半部分。

同時,為了避免這種新增,我們可以對問題進行改造。 也就是說,從陣列 a 的所有數字中減去 **g,這樣問題就會轉化為找到總和 0 的組合,即,您可以找到總和 和 **g * i 的組合。

雙端搜尋語言支援:python3

class solution(object): def splitarraysame**erage(self, a): from fractions import fraction n = len(a) total = sum(a) a = [a - fraction(total, n) for a in a] 轉換後,如果 n == 1,則免於計算總和:返回 false s1 = set() 範圍 (n 2) 中 i 的所有可能的 b 和的集合: 在前乙個選擇的基礎上選擇 a[i] 的新集合是僅選擇a[i] s1 是不選擇 a[i] |是乙個集合並運算 s1 = |s1 |如果 s1 中的 0: 返回 true s2 = set() 範圍(n 2, n) 中 i 的所有可能 c 和的集合: s2 = |s2 |如果 S2 中的 0:如果 S1 和 S2 都沒有 0 的總和組合,則返回 true。 然後我們需要分別從 s1 和 s2 中找到 a 和 b,看看總和是否可以達到 0如果是這樣,描述也將滿足問題的含義 為了避免 b 或 c 為空,我們新增這樣的判斷:(ha, -ha) != (sleft, sright) sleft = sum(a[i] for i in range(n//2)) sright = sum(a[i] for i in range(n//2, n)) return any(-ha in s2 and (ha, -ha) != (sleft, sright) for ha in s1)
複雜性分析

設 n 為陣列的長度。

時間複雜度:$o(2 (n 2))$ 空間複雜度:$o(2 (n 2))$

相關問題答案

    LeetCode 陣列和矩陣

    給定陣列 a ,,n 請構造乙個陣列 b ,,n 其中元素 b i a a a i a i a n 不能使用除法。注 b a a a n b n a a a n 想法 假設 left i a a i right i a i a n 所以 b i left i right i 可以知道 left i ...

    LeetCode 215 陣列中的第 k 個最大元素

    在未排序的陣列中找到第 k 個最大的元素。請注意,您正在尋找按陣列排序的第 k 個最大元素,而不是第 k 個不同的元素。示例 輸入 ,,,,, 和 k 輸出 示例 輸入 ,,,,,,,, 和 k 輸出 描述 您可以假設 k 始終有效,並且 k 陣列的長度是好的。快速選擇阿里騰訊位元組的問題要求在無序...

    Leetcode 2009 使陣列具有最少的運算元

    給你乙個整數 nums 陣列。在每個操作中,您都可以將 nums 中的任何元素替換為任意整數。如果 Nums 滿足以下條件,則它是連續的 nums 中的所有元素彼此不同。nums 中最大元素和最小元素之間的差值等於 numslength 例如,nums ,,, 是連續的,但 nums ,,,, 不是...

    LeetCode 820 單詞的壓縮編碼

    給定乙個單詞列表,我們將列表編碼為索引字串 s 和索引列表 a。例如,如果此列表為 time me bell 我們可以將其表示為 s time bell 和索引 ,, 對於每個索引,我們可以從索引在字串 s 中的位置開始讀取字串,直到 以恢復我們之前的單詞列表。那麼,成功編碼給定單詞列表的最小字串長...

    判斷陣列的方法有哪些?

    關鍵字 js 方法判斷陣列。有幾種方法可以判斷值是否是 j ascript 中的陣列,但這裡有一些常見的方法 用array.isarray 方法可以確定值是否為陣列。這是 ES 中的乙個新方法,它返回乙個布林值。const arr ,, console.log array.isarray arr t...