給定一個整數數組,例如[1, 2, -3, 1]
查找是否存在與0
相加的子序列並返回它(例如[1, 2, -3]
或[2, -3, 1]
)。
檢查每個子序列的效率太低,爲O(n^2)
。任何改進想法?子序列總數
子序列總數
回答
創建一個新的數組,每個元素等於之前元素加上那個元素的總和。
輸入:
1 4 -3 -4 6 -7 8 -5
變爲:
1 5 2 -2 4 -3 5 0
^ ^
然後尋找匹配所得數組中的元素。因爲它們代表函數整體變化爲零的位置,你會發現如果它們的位置是i和k,那麼子序列(i + 1,k)就是一個零和子序列。 (在這種情況下,[2:6])。
此外,表中的任何零指示子序列(0,k)是零和子序列。對於查找,散列表或其他快速碰撞定位器使得該O(N)能夠執行。
這很好。你能指出關於這個特定解決方案的任何鏈接或文獻嗎?這個問題和/或解決方案是否有正式名稱? – istepaniuk 2014-05-20 21:24:09
你們如何看待這些東西/甚至認爲這樣做?我從來沒有想過要這樣做。 – kidcapital 2015-12-11 18:38:37
我不記得了,已經過了幾年了:P – argentage 2015-12-12 00:10:19
做的運行總和,在哈希表中存儲和值與數組索引
沿着如果你有機會,你已經看到了一個和值,返回1 +索引在哈希表,以及當前指數。 此解決方案是O(n)時間複雜性。
不需要新的陣列。由於散列,空間複雜度爲O(N)。
Python實現:
input = [1, 4, -3, -4, 6, -7, 8, -5]
map = {}
sum = 0
for i in range(len(input)):
sum += input[i]
if sum in map:
print map[sum][0] + 1, "to", i
map[sum] = (i, sum)
注意,重複的子序列中未示出,例如: 如果(1至2)是一個子序列和(3至4),(1〜4 )將不會顯示。您可以通過在地圖上的每個位置存儲列表實現這一行爲:
for x in map[sum]:
print x[0]+1, "to", i
map[sum].append((i, sum))
您忽略了計算散列表所需的空間。爲了高效散列表行爲,它必須大於可能值的集合。 – nneonneo 2015-06-17 17:09:34
@nneonneo是真的,補充。 – 2015-06-17 17:40:22
A C++實現類似於法布里西奧的回答邏輯。
pair<int, int> FindSubsequenceSum(const vector<int>& arr)
{
map<int, int> sumMap;
map<int, int>::iterator it;
int sum = 0;
for (int i = 0; i < arr.size(); i++)
{
sum += arr[i];
it = sumMap.find(sum);
if (it != sumMap.end())
{
return make_pair(it->second + 1, i);
} else {
sumMap.insert(make_pair(sum, i));
}
}
int main()
{
int arr[] = {1,4,-3,-4,6,-7,8,-5};
vector<int> input(arr, arr + sizeof(arr)/sizeof(arr[0]));
pair<int, int> result = FindSubsequenceSum(input);
cout << "(" << result.first << "," << result.second << ")" << endl;
return 0;
}
Output:
(2,6)
下面是Java實現的解決方案通過@Fabricio
建議public static int countAllSubSequenceForZeroSum(int[] array) {
int count = 0;
Map<Integer, Integer> encounteredSum = new HashMap<>();
int prev = array[0];
if(prev == 0) {
count++;
System.out.println("Found at index: "+0);
}
for (int i = 1; i < array.length; i++) {
prev += array[i];
if(encounteredSum.containsKey(prev)) {
System.out.println("Found at index: "+i+ " start index: "+encounteredSum.get(prev));
printSequenceForZeroSum(array, i);
count++;
} else {
encounteredSum.put(prev, i);
}
}
return count;
}
public static void printSequenceForZeroSum(int[] array, int endIndex) {
int sum = array[endIndex];
while(sum!=0) {
System.out.print(array[endIndex]+ " ");
sum += array[--endIndex];
}
System.out.println(array[endIndex]);
}
- 1. 計算其總和可被k整除的子序列總數
- 2. Python總和素因子函數產生有限序列
- 3. 基於列總和的分位數的子集數據(列)
- 4. 最大總和子列表?
- 5. 子陣列的總和
- 6. 子查詢列的總和
- 7. 打印整數陣列的每個連續子序列的總和
- 8. 作出序列的數字總和
- 9. 彙總時間序列數據
- 10. 即時彙總時間序列數據
- 11. 子集總和程序
- 12. Datagridview列總數
- 13. 最長的子序列數
- 14. 數組的子序列
- 15. 與正數總和的列表的子列表
- 16. 在網格項模板列中彙總子數據源數據列列
- 17. postgresql每列總數
- 18. 數組列總和
- 19. PHP MySQL列總數
- 20. Linq彙總序列號
- 21. 彙總組合序列
- 22. 子數據集 - 列表中的總行數
- 23. 長度和最長增加的子序列的總和
- 24. x元素的最大連續子序列總和
- 25. 以int爲單位的最大總和的子序列
- 26. 如何查找循環鏈表中的最大子序列總數
- 27. 計算子窗體總數
- 28. 總和子數組的值
- 29. 用vfork和子女總數()
- 30. SQLite:獲得總數/總和列
我將它張貼在這裏:http://cs.stackexchange.com/。順便說一下,我不認爲每個子序列都是O(n^2)。它應該是O(2^n),即指數。用O(n^2)代替在線方法。 – 2013-02-14 00:33:34
如果它們是連續的子序列,則有n-1 * n-2個組合 – argentage 2013-02-14 01:02:59
連續的子序列?或任何子序列?形式上,「子序列」一詞並不意味着連續性。你的例子是非確定性的。 – AnT 2013-02-14 01:20:56