Рассмотрим следующую постановку проблемы:

Учитывая несортированный массив целых чисел, найдите подмассив, который добавляет к заданному числу. Если существует более одного подмассива с суммой в качестве данного числа, выведите любой из них.

Examples:

Input: arr[] = {1, 4, 20, 3, 10, 5}, sum = 33
Ouptut: Sum found between indexes 2 and 4

Input: arr[] = {10, 2, -2, -20, 10}, sum = -10
Ouptut: Sum found between indexes 0 to 3

Input: arr[] = {-10, 0, 2, -2, -20, 10}, sum = 20
Ouptut: No subarray with given sum exists

На этом сайте следующие Было предложено решение с линейным временем, включающее использование карты для хранения сумм текущих подмножеств, когда алгоритм выполняет итерацию по массиву:

// Function to print subarray with sum as given sum
void subArraySum(int arr[], int n, int sum)
{
    // create an empty map
    unordered_map<int, int> map;

    // Maintains sum of elements so far
    int curr_sum = 0;

    for (int i = 0; i < n; i++)
    {
        // add current element to curr_sum
        curr_sum = curr_sum + arr[i];

        // if curr_sum is equal to target sum
        // we found a subarray starting from index 0
        // and ending at index i
        if (curr_sum == sum)
        {
            cout << "Sum found between indexes "
                 << 0 << " to " << i << endl;
            return;
        }

        // If curr_sum - sum already exists in map
        // we have found a subarray with target sum
        if (map.find(curr_sum - sum) != map.end())
        {
            cout << "Sum found between indexes "
                 << map[curr_sum - sum] + 1
                 << " to " << i << endl;
            return;
        }

        map[curr_sum] = i;
    }

    // If we reach here, then no subarray exists
    cout << "No subarray with given sum exists";
}
// Driver program to test above function
int main()
{
    int arr[] = {10, 2, -2, -20, 10};
    int n = sizeof(arr)/sizeof(arr[0]);
    int sum = -10;

    subArraySum(arr, n, sum);

    return 0;
}

В тестовом примере, который представлен в сообщении, второй оператор if, проверяющий, вводится ли current_sum - sum, никогда не вводится. Вместо этого сумма находится и печатается в первом операторе if. Итак, здесь есть несколько недоразумений :

1: Какова цель поиска current_sum-sum на карте?

2: В каких случаях можно было бы ввести второй оператор if, чтобы использовать карту для решения проблемы?

12
loremIpsum1771 5 Сен 2016 в 01:25

2 ответа

Есть два случая:

  1. Сумма от индексов 0 до n - это число, которое мы ищем. cur_sum - это текущая сумма всех индексов, так что это так же просто, как просто проверить эту переменную.

  2. Сумма индексов от m до n - это число, которое мы ищем. Если это так, то существует m такое, что (сумма от 0 до n) минус (сумма от 0 до m) является суммой, которую мы ищем. Все эти промежуточные суммы хранятся на карте, поэтому мы ищем cur_sum - sum - если эта разница соответствует некоторой частичной сумме, то все готово.

    Примером этого второго случая может быть первый тестовый случай в вашем вопросе - поиск 33 в {1, 4, 20, 3, 10, 5}. В n==4 у нас есть cur_sum из 38. Но 5 присутствует на карте как сумма первых двух индексов.

16
Community 20 Июн 2020 в 09:12

Карта не нужна, если в массиве нет отрицательных целых чисел. В этом случае вы можете просто сохранить начальную переменную, вычитая arr [start] из currSum и увеличивая start на 1, пока currSum> sum.

В случае, если в массиве могут быть отрицательные целые числа, можно использовать этот метод с картой.

Попробуйте этот пример, чтобы понять решение:

-5, 2, 10, 20, 3, 8

Сумма = 33

Ответ: сумма, найденная между индексами от 2 до 4

-1
Anup Verma 29 Сен 2017 в 19:23