Subsequence sum

匿名 (未验证) 提交于 2019-12-03 02:44:02

问题:

Given an array of integers eg [1, 2, -3, 1] find whether there is a sub-sequence that sums to 0 and return it (eg [1, 2, -3] or [2, -3, 1]).
Checking every sub-sequence is O(n^2) which is too inefficient. Any idea for improvements?

回答1:

Make a new array with each element equal to the sum of the previous elements plus that one.

Input:

1  4 -3 -4  6  -7  8 -5

Becomes:

1  5  2  -2  4  -3  5  0    ^                ^

Then look for elements that match in the resulting array.

Since these represent locations where the overall change in the function is zero, you will find that if their position is i and k then the subsequence (i+1, k) is a zero-sum subsequence. (In this case, [2:6]).

Additionally, any zeros in the table indicate that the subsequence (0, k) is a zero-sum subsequence. For the lookup, a hash table or other fast collision locator makes this O(N) to perform.



回答2:

Do a running sum, storing sum values in a hash table along with array index

If you ever get a sum value you’ve already seen, return 1+the index in the hash table, and the current index. This solution is O(n) time complexity.

No need for a new array. Space complexity is O(N) because of the hash.


A Python implementation:

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)

Notice that repeated subsequences are not shown, example: If (1 to 2) is a subsequence and (3 to 4), (1 to 4) won't be shown. You can achieve this behavior by storing lists in each position of the map:

for x in map[sum]:     print x[0]+1, "to", i map[sum].append((i, sum))


回答3:

Below is the java implementation of the solution suggested by @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]); }


回答4:

A C++ implementation with logic similar to Fabricio's answer.

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)


转载请标明出处:Subsequence sum
文章来源: Subsequence sum
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!