Пожалуйста, прочитайте описание проблемы здесь: https://leetcode.com/problems/two-sum/

Из описания задачи видно, что нам дана функция с двумя переменными:

  1. Массив со списком чисел
  2. Целое число, являющееся целевым значением суммы.

Мы должны вернуть два индекса двух чисел, которые при сложении вместе мы получим целевое значение.

В этой статье я покажу вам два способа решения проблемы с помощью Javascript. Первое решение будет наивным, а следующее решение будет оптимизированным.

Решение 1 (Наивный подход)

Для первого решения мы будем использовать два вложенных цикла.

/**
* @param {number[]} nums
* @param {number} target
* @return {number[]}
*/
var twoSum = function(nums, target) {
    /*
     *1. The Outer loop, picks one value from the array at a time.
     */
    for(let i=0;i<nums.length;i++){
        /*
         *The inner loops through the array(separately) and compares
         *each value with with the value picked by the outer loop.
         */
        for(let j=0;j< nums.length;j++){
            /*
            *To prevent numbers from the same index from being  
            *compared we check ensure indices i and j are not equal.
            */
            if(j!=i){  
               /*If the difference between the target and the loop1
                *value are equal to the inner loop value we have
                *found a match and we return
                *the two indices
                */           
                 if((target-nums[i])==nums[j]){
                    return [i,j]
                 }
            }
        }
    }
};

Решение работает, хотя его временная сложность равна O(n^2), что означает, что количество запусков кода равно квадрату длины массива nums. Например, если у нас есть nums=[2,7,9,11] и target=9, это будет лучший сценарий нашего кода, поскольку цель будет найдена, когда мы итерируем внешний цикл один раз и внутренний цикл дважды, т.е. значение будет [0,1], так как 2+7=9. Другой сценарий — когда у нас есть решения в конце массива nums, т. е. nums=[8,11,2,7] и target=9. В этом случае внешний цикл будет выполняться 3 раза, прежде чем будет найдена одна часть решения, то есть 2. Каждый раз, когда внешний цикл выполняется один раз, внутренний цикл выполняется четыре раза, что означает, что в этом случае наши внутренние циклы выполняются 12 раз, прежде чем найти решение. В еще худшем случае, когда у нас нет решения, например, nums=[8,11,3,3] и target=9, это означает, что наш внешний цикл будет выполняться четыре раза. Внутренний цикл будет выполняться четыре раза для каждой итерации внешнего цикла. Следовательно, общее количество запусков внутреннего цикла будет 4*4=16. Если длина массива nums равна 4, внутренний цикл выполняется не более 16 раз, если длина массива nums равна 10 000, внутренний цикл выполняется не более 10 000 * 10 000 = 100 000 000 раз. Поэтому максимальное количество запусков внутреннего цикла равно квадрату длины массива nums, следовательно, обозначение сложности O(n^2). Поскольку мы не храним никаких данных, сложность нашего хранилища составляет O (1), т. е. она не увеличивается с размером входных данных.

Решение 2

Для этого решения мы хотим улучшить нашу сложность времени выполнения с O (n ^ 2) до O (n), однако мы будем использовать карты. Карты можно использовать для хранения пар ключ-значение. Поэтому для каждого сохраненного ключа у нас должно быть значение, обеспечивающее более быстрый способ получения информации. В нашем случае ключом является разница между целью и числом по текущему индексу. Значением карты является текущий индекс.

Наше оптимизированное решение будет иметь сложность хранения O(n).

/**
* @param {number[]} nums
* @param {number} target
* @return {number[]}
*/
var twoSum = function(nums, target) {
    //We initialize our map using JS inbuilt class
    let map=new Map();
    /*
     *We only use one loop to iterate through the array once,
     *therefore improving on the time complexity of our solution.
     */
    for(let i=0; i<nums.length; i++){
        //We check if the current number exists as a key in our map.
        if(!map.has( nums[i] )){
            /*If the number does not exist, we calculate the
             *difference between the target and the current number,
             *set is as a key with the current index as a value.
             */
             map.set( target-nums[i] , i )
        } else {
            /*If the current number exists, it means there is
             *another number in our map which if added with the
             *current number we get the target. We use the map.get()
             *function to retrieve the index. We then return the two      
             *indexes.
             */
           return [ map.get( nums[i] ) , i ]
        }
     }
};