web-dev-qa-db-fra.com

Somme de sous-séquence

Par exemple, [1, 2, -3, 1] donne un tableau d'entiers, par exemple, cherche s'il existe une sous-séquence dont le résultat est 0 et la renvoie (par exemple, [1, 2, -3] ou [2, -3, 1]).
Vérifier chaque sous-séquence est O(n^2) qui est trop inefficace. Une idée d'amélioration?

18
user1762571

Créez un nouveau tableau avec chaque élément égal à la somme des éléments précédents plus celui-là.

Contribution:

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

Devient:

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

Ensuite, recherchez les éléments qui correspondent dans le tableau résultant.

Comme ils représentent des emplacements où le changement global de la fonction est nul, vous constaterez que si leur position est i et k, la sous-séquence (i + 1, k) est une sous-séquence à somme nulle. (Dans ce cas, [2: 6]).

De plus, les zéros de la table indiquent que la sous-séquence (0, k) est une sous-séquence à somme nulle. Pour la recherche, une table de hachage ou un autre localisateur de collision rapide permet à cette O(N) d'effectuer.

36
argentage

Faire une somme en cours, en stockant les valeurs de somme dans une table de hachage avec un index de tableau

Si vous obtenez une valeur de somme que vous avez déjà vue, renvoyez 1 + l'index de la table de hachage et l'index actuel. Cette solution est O(n) temps complexité.

Pas besoin d'un nouveau tableau. La complexité de l'espace est O(N) à cause du hachage.


Une implémentation en 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)

Notez que les sous-séquences répétées ne sont pas affichées, exemple: Si (1 à 2) est une sous-séquence et que (3 à 4), (1 à 4) ne sera pas affiché. Vous pouvez obtenir ce comportement en stockant des listes à chaque position de la carte:

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

Vous trouverez ci-dessous l'implémentation Java de la solution proposée par @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]);
}
2
Bhumik Thakkar

Une implémentation C++ avec une logique similaire à la réponse de Fabricio.

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)
0
Bikash