C/C++

Leetcode. Обнулить строки и столбцы матрицы с константным потреблением памяти.

Интересная штука попалась: https://leetcode.com/problems/set-matrix-zeroes/

Задача - обнулить те строки и столбцы матрицы N x M, в которых встречается хотя бы один ноль.


Естественно, проблема мгновенно решается с временным буфером размером O(N x M), после 5 секунд раздумий уже хватает памяти O(N + M) - учёт обнуляемых строк и столбцов в отдельных одномерных массивах длины M и N, соответственно, - но это неспортивно. А вот чтобы сделать O(1), я думал больше суток. Не всё время, конечно, ещё надо когда-то работать и спать... Искал идеи на stackoverflow - без толку, там другие задачи (например, матрица из единиц и нулей, и решение не подходит).

Интересно, здесь кто-то сможет решить с памятью O(1)? Для разнообразия от игровых движков и поиска подстрок в строке...
Есть способ, который правда займет побольше времени. Учитывая что максимальный размер 200*200 - вполне за разумное время можно найти любое число, которое не встречается в текущей матрице и принять его за мнимый ноль. Дальше все просто - от каждого нуля помечать во все стороны числа, отличные от нуля - мнимым нулем. А в конце - заменить все мнимые нули - настоящими нулями.

PS: а какое решение предложено для булевой матрицы на стакфлоу? По моему оно сложнее моего, ибо там мнимого нуля не найти)
Вадим Цыганий
Вадим Цыганий
51 417
Лучший ответ
Сергей Шевченко в источнике /смотрю сейчас/ в функцию подаётся стандартный вектор,
так что поиск стандартной функцией STL и потом присвоение вектору в матрице вектора с заранее нулевыми значениями. Иначе используем динамику с итерацией указателей для улучшения алгоритма поиска и замены )))
void setZeroes(vector<vector<int>>& matrix) { }
Сергей Шевченко я не пойму что там вообще им нужно? STL и vector и чего там O искать?? Всё уже стандартно найдено!?
Вадим Цыганий
 Сайт успешно схавал мое решение. Посмотрел как у других - а оказывается все элементарно и просто.
Проверяем нужно ли обнулять начальные столбец и строку (и помечаем этот факт в отдельной переменной). А далее ищем нули в остальной матрице. При нахождении - выносим его проекцию на начальные столбец и строку. После этого обнуляем не нулевые строки и столбцы, где были проекции нулей. И в конце обнуляем нулевой столбец и нулевую строку, если это требовалось.
Решение на O(2)

На первом проходе находим и запоминаем с помощью ассистента индексы нулевых элементов.

На втором проходе обнуляемся.

Ассистент хранит индексы в хеш-таблице, в которой время поиска заданного индекса константное и составляет O(1).
 #include  
#include
#include

using namespace std;

class Solution {
public:
void setZeroes(vector& matrix) {
const auto rows = matrix.size();
const auto columns = matrix[0].size();
Assistant assistant;
for (size_t i = 0; i < rows; ++i) {
for (size_t j = 0; j < columns; ++j) {
if (matrix[i][j] == 0) {
if (!assistant.rows.contains(i)) {
assistant.rows.insert(i);
}
if (!assistant.columns.contains(j)) {
assistant.columns.insert(j);
}
}
}
}
for (size_t i = 0; i < rows; ++i) {
for (size_t j = 0; j < columns; ++j) {
if (assistant.rows.contains(i) || assistant.columns.contains(j)) {
matrix[i][j] = 0;
}
}
}
}
private:
struct Assistant {
unordered_set rows;
unordered_set columns;
};
};

void showMatrix(const vector& matrix) {
for (const auto& row : matrix) {
for (const auto value : row) {
cout
Efiop ***
Efiop ***
93 064
~ Нарек ~ Верните настоящего Веселуху!
Время исследования последовательности не может не зависеть от ее размера. А вообще задача о потреблении памяти. Цитата: Could you devise a
constant space solution?
Мишка Гамми Щас тебе автор напишет что типо чатгпт
Андрей Крестников Потребление памяти по замерам этого сайта и у моих решений - почти всегда днищенское, причём, слабо зависящее от асимптотики. Я думаю, у них просто в какой-то момент вырос на пару мегабайт размер сишного рантайма (который и составляет большую часть потребления), а статистика осталась старая. А время - вообще жесть. Жму на один и тот же код 3 раза сабмит - 3 разных времени. Делать замеры на прогретых кэшах и считать среднее или минимум от 3-х попыток их явно не научили.

Решение O(n * n) по памяти эта штука тоже принимает, а комментарии вроде "сделайте за O(1)" там написаны для тех, кому скучно решать в лоб. Как мне, например.
Сам спросил сам и ответил
ВВ
Виталий В
14 368