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
?
Je suis sûr qu'il existe un meilleur moyen, mais voici une idée:
Ces deux opérations sont O(n log n)
.
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)
.
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.
Disons que nous voulons trouver deux nombres dans le tableau A qui, une fois additionnés, sont égaux à N.
Le tri peut être fait en O (n log n). La recherche est faite en temps linéaire.
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);
}
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
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
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
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).
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;
}
É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--;
}
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);
}
}
}
}
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>
A) TimeComplexity => 0 (n Journal n) SpaceComplexity => 0 (n).
B) TimeComplexity => 0 (n ^ 2) SpaceComplexity => 0 (1).
C) TimeComplexity => 0(n) SpaceComplexity => 0 (n)
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 []
}