Лучшие решения для задач Microsoft на собеседовании. Разделите массив на N подмножеств со сбалансированной суммой.
Описание:
Дайте вам один отсортированный массив, поместите их в n сегментов, нам нужно убедиться, что мы получаем n подмассивов с примерно равными весами.
Пример:
вход {1, 2, 3, 4, 5} n = 3
вывод [[5], [1,4], [2,3]];
Решение:
Обычно эта задача выглядит как типичная проблема с разделами https://en.wikipedia.org/wiki/Partition_problem
К сожалению, это описание выглядит нечетким или слишком общим, поскольку оно не описывает, что именно означает «приблизительно равные веса», поэтому я не думаю, что этот вопрос будет задан таким образом на собеседовании. Вам нужно будет узнать подробности у интервьюера и выбрать правильный подход.
Есть много подходов к решению этой проблемы, оптимизированных для особых случаев. В случае, если мы ничего особенного не знаем о входных данных и требованиях, поэтому, на мой взгляд, лучшим решением будет использовать самый простой и базовый подход - жадный алгоритм. Https://en.wikipedia.org/wiki/Greedy_algorithm
Жадный алгоритм основан на простой идее: мы берем наибольшее значение из входного массива и помещаем его в раздел с наименьшей суммой. Наш входной массив уже отсортирован по описанию, поэтому мы можем брать значения по очереди. Чтобы выбрать раздел с наименьшей суммой, мы можем оставить разделы в очереди с приоритетом, которая отсортирована по сумме этих разделов.
Код C ++:
vector<vector<int>> part(const vector<int> & v, int n) { int v_size = v.size(); // in this vector we will keep sums of the partitions vector<int> sums(n, 0); // in this priority queue we will keep values of the priorities // it is just numbers from 0 to numbers of partitions. // We will use these numbers as indexes // to access sums and to definition priorities of the partitions // in other words the sums tied with the partitions by // these priority values. // Pay attention that the sums we keep in the external // vector described above, // so we need to declare a special comparator // for the queue in order to sort the queue by the // priority values. auto compare = [&sums](int a, int b) { return sums[a] >= sums[b]; }; priority_queue<int, std::vector<int>, decltype(compare)> pq(compare); // here we will keep values of the partitions vector<vector<int>> result(n, vector<int>()); // generate numbers of the priority values. for (int i = 0; i < n; i++) { pq.push(i); } // The input array is sorted ascending so we will process // it from the back to the front. for (int i = v_size - 1; i >= 0; --i) { // take the highest priority from the queue int c = pq.top(); pq.pop(); // put the max value from the input array to the partition // with the highest priority, // that is partition with the lowest sum. result[c].push_back(v[i]); // increase the lowest sum to max value from // the input array. sums[c] += v[i]; // push back the priority value. After this call the queue // will be resorted corresponding to // new value of the sums array. pq.push(c); } return result; }
Репозиторий с полной версией проекта вы можете найти здесь: https://github.com/jolly-fellow/microsoft/tree/master/partition_array_into_n_subsets_with_balanced_sum
Вернуться к оглавлению.