web-dev-qa-db-fra.com

Comment écrire un algorithme pour vérifier si la somme de deux nombres quelconques dans un tableau/une liste correspond à un nombre donné?

Comment puis-je écrire un algorithme pour vérifier si la somme de deux nombres dans un tableau/liste correspond à un nombre donné Avec une complexité de nlogn?

20
Bunny Rabbit

Je suis sûr qu'il existe un meilleur moyen, mais voici une idée:

  1. Trier le tableau
  2. Pour chaque élément e du tableau, recherche binaire du complément (somme - e)

Ces deux opérations sont O(n log n).

31
Andreas Brinck

Cela peut être fait dans O(n) en utilisant une table de hachage. Initialisez la table avec tous les nombres du tableau, avec le chiffre comme clé et la fréquence comme valeur. Parcourez chaque nombre dans le tableau et voyez si (sum - number) existe dans la table. Si c'est le cas, vous avez une correspondance. Une fois que vous avez parcouru tous les nombres du tableau, vous devriez avoir une liste de toutes les paires qui totalisent le nombre souhaité.

array = initial array
table = hash(array)
S = sum

for each n in array
    if table[S-n] exists
        print "found numbers" n, S-n

Le cas où n et la table [S-n] font référence au même numéro deux fois peut faire l’objet d’une vérification supplémentaire, mais la complexité reste O(n).

26
Anurag

Utilisez une table hash . Insérez chaque nombre dans votre table de hachage, ainsi que son index. Ensuite, laissez S être votre somme désirée. Pour chaque nombre array[i] dans votre tableau initial, vérifiez si S - array[i] existe dans votre table de hachage avec un index différent de i.

Le cas moyen est O(n), le pire des cas est O(n^2), utilisez donc la solution de recherche binaire si vous avez peur du pire.

20
IVlad

Disons que nous voulons trouver deux nombres dans le tableau A qui, une fois additionnés, sont égaux à N.

  1. Triez le tableau.
  2. Recherchez le plus grand nombre du tableau inférieur à N/2. Définissez l’index de ce nombre comme suit: lower .
  3. Initialize upper to be lower + 1.
  4. Définissez somme = A [ inférieur ] + A [ supérieur ].
  5. Si sum == N, c'est fait.
  6. Si sum <N, incrémenter supérieur .
  7. Si somme > N, décrémentez plus bas .
  8. Si lower ou upper est en dehors du tableau, cela sans correspondance.
  9. Retournez à 4.

Le tri peut être fait en O (n log n). La recherche est faite en temps linéaire.

10

Ceci est en Java: Cela supprime même les doublons possibles. Runtime - O(n^2)

private static int[] intArray = {15,5,10,20,25,30};
private static int sum = 35;

private static void algorithm()
{
    Map<Integer, Integer> intMap = new Hashtable<Integer, Integer>();
    for (int i=0; i<intArray.length; i++) 
    {
        intMap.put(i, intArray[i]);
        if(intMap.containsValue(sum - intArray[i]))
            System.out.println("Found numbers : "+intArray[i] +" and "+(sum - intArray[i]));

    }
    System.out.println(intMap);
}
4
First Blood
def sum_in(numbers, sum_):
    """whether any two numbers from `numbers` form `sum_`."""
    a = set(numbers) # O(n)
    return any((sum_ - n) in a for n in a) # O(n)

Exemple:

>>> sum_in([200, -10, -100], 100)
True
2
jfs

Voici un algorithme qui s'exécute dans O(n) si le tableau est déjà trié ou O (n log n) s'il n'est pas déjà trié. Prend des indices de beaucoup d'autres réponses ici. Le code est en Java, mais voici un pseudo-code dérivé de nombreuses réponses existantes, mais optimisé pour les doublons en général

  1. Devinez si les premier et dernier éléments sont égaux à la cible
  2. Créer une carte avec la valeur actuelle et ses occurrences
  3. Créer un ensemble visité contenant des éléments déjà vus, optimisé pour les doublons, par exemple avec une entrée de (1,1,1,1,1,1,2) et de la cible 4, nous calculons uniquement pour le dernier élément et pas tous les 1 dans le tableau.
  4. Utilisez ces variables pour calculer l’existence de target dans le tableau.

    ET ne retourne vrai que si A. nous n'avons jamais vu cet entier avant AND b. nous avons une certaine valeur pour le newTarget dans la carte que nous avons créée c. et le nombre pour newTarget est égal ou supérieur au nombre attendu

AUTREMENT répétez l'étape 4 jusqu'à atteindre la fin du tableau et retournons false, AUTREMENT;

Comme je l'ai mentionné, la meilleure utilisation possible pour un magasin visité est lorsque nous avons des doublons, cela n'aidera jamais si aucun des éléments n'est dupliqué.

Code Java à https://Gist.github.com/eded5dbcee737390acb4

1
Keith Dsouza

Voici un essai en C. Ce n'est pas un devoir marqué.

// Assumes a sorted integer array with no duplicates
void printMatching(int array[], int size, int sum)
{
   int i = 0, k = size - 1;
   int curSum;
   while(i < k)
   {
      curSum = array[i] + array[k];
      if(curSum == sum)
      {
         printf("Found match at indices %d, %d\n", i, k);
         i++;k--;
      }
      else if(curSum < sum)
      {
         i++;
      }
      else
      {
         k--;
      }
   }
}

Voici quelques résultats de test utilisant int a[] = { 3, 5, 6, 7, 8, 9, 13, 15, 17 };

Searching for 12..
Found match at indices 0, 5
Found match at indices 1, 3
Searching for 22...
Found match at indices 1, 8
Found match at indices 3, 7
Found match at indices 5, 6
Searching for 4..
Searching for 50..

La recherche est linéaire, donc O (n). La sorte qui se passe dans les coulisses va être O (n * logn) si vous utilisez l'une des bonnes sortes.

En raison du calcul derrière Big-O, le terme plus petit en termes additifs disparaîtra effectivement de votre calcul et vous aboutirez à O (n logn).

1
Phil

Celui-ci est O (n)

public static bool doesTargetExistsInList(int Target, int[] inputArray)
{
    if (inputArray != null && inputArray.Length > 0 )
    {
        Hashtable inputHashTable = new Hashtable();

        // This hash table will have all the items in the input array and how many times they appeard
        Hashtable duplicateItems = new Hashtable();

        foreach (int i in inputArray)
        {
            if (!inputHashTable.ContainsKey(i))
            {
                inputHashTable.Add(i, Target - i);
                duplicateItems.Add(i, 1);
            }
            else
            {
                duplicateItems[i] = (int)duplicateItems[i] + 1;    
            }

        }

        foreach (DictionaryEntry de in inputHashTable)
        {
            if ((int)de.Key == (int)de.Value)
            {
                if ((int)duplicateItems[de.Key] > 1)
                return true;
            }
            else if (inputHashTable.ContainsKey(de.Value))
            {
                return true;
            }
        }
    }
    return false;
}
1
Abdel

Étape 1: Triez le tableau dans O (n logn)

Étape 2: Trouvez deux indices 

0 <= i <j <= n dans un [0..n] tels que a [i] + a [j] == k, où k est donné clé.

int i=0,j=n;
while(i<j) {
   int sum = a[i]+a[j];
   if(sum == k)
        print(i,j)
   else if (sum < k)
        i++;
   else if (sum > k)
        j--;
}
0
BVMR
    public void sumOfTwoQualToTargetSum()
    {
        List<int> list= new List<int>();
        list.Add(1);
        list.Add(3);
        list.Add(5);
        list.Add(7);
        list.Add(9);

        int targetsum = 12;

        int[] arr = list.ToArray();

        for (int i = 0; i < arr.Length; i++)
        {
            for (int j = 0; j < arr.Length; j++)
            {
                if ((i != j) && ((arr[i] + arr[j]) == targetsum))
                {
                    Console.Write("i =" + i);
                    Console.WriteLine("j =" + j);
                }
            }
        }
    }
0
rshalucse

Dépend Si vous voulez une seule somme O(N) ou O (N log N) ou toutes les sommes O (N ^ 2) ou O (N ^ 2 log N). Dans ce dernier cas, il vaut mieux utiliser une FFT>

0
Guest20072013
  1. Résolu la question dans Swift 4.0
  2. Résolu de 3 manières différentes (avec 2 types de déclaration différents -> Booléen et Index)

A) TimeComplexity => 0 (n Journal n) SpaceComplexity => 0 (n). 

B) TimeComplexity => 0 (n ^ 2) SpaceComplexity => 0 (1). 

C) TimeComplexity => 0(n) SpaceComplexity => 0 (n)

  1. Choisissez la solution A, B ou C en fonction de TradeOff. 

    //***********************Solution A*********************//
    //This solution returns TRUE if any such two pairs exist in the array
    func binarySearch(list: [Int], key: Int, start: Int, end: Int) -> Int? { //Helper Function
    
                if end < start {
                    return -1
                } else {
                    let midIndex = (start + end) / 2
    
                    if list[midIndex] > key {
                        return binarySearch(list: list, key: key, start: start, end:  midIndex - 1)
                    } else if list[midIndex] < key {
                        return binarySearch(list: list, key: key, start: midIndex + 1, end: end)
                    } else {
                        return midIndex
                    }
                }
            }
    
            func twoPairSum(sum : Int, inputArray: [Int]) -> Bool {
    
                //Do this only if array isn't Sorted!
                let sortedArray = inputArray.sorted()
    
                for (currentIndex, value)  in sortedArray.enumerated() {
                    if let indexReturned =  binarySearch(list: sortedArray, key: sum - value, start: 0, end: sortedArray.count-1) {
                        if indexReturned != -1 && (indexReturned != currentIndex) {
                            return true
                        }
                    }
                }
                return false
            }
    
     //***********************Solution B*********************//
     //This solution returns the indexes of the two pair elements if any such two pairs exists in the array
     func twoPairSum(_ nums: [Int], _ target: Int) -> [Int] {
    
                for currentIndex in 0..<nums.count {
                    for nextIndex in currentIndex+1..<nums.count {
                        if calculateSum(firstElement: nums[currentIndex], secondElement: nums[nextIndex], target: target) {
                            return [currentIndex, nextIndex]
                        }
                    }
                }
    
                return []
            }
    
            func calculateSum (firstElement: Int, secondElement: Int, target: Int) -> Bool {//Helper Function
                return (firstElement + secondElement) == target
            }
    
        //*******************Solution C*********************//
       //This solution returns the indexes of the two pair elements if any such two pairs exists in the array
       func twoPairSum(_ nums: [Int], _ target: Int) -> [Int] {
    
                var dict = [Int: Int]()
    
                for (index, value) in nums.enumerated() {
                    dict[value] = index
                }
    
                for (index, value) in nums.enumerated() {
                    let otherIndex = dict[(target - value)]
                    if otherIndex != nil && otherIndex != index {
                        return [index, otherIndex!]
                    }
                }
    
                return []
            }
    
0
redEyeProgrammer