Преобразование матрицы
Задача
Преобразовать матрицу, чтобы она была срезана по y координате. Пример:
x = [[1, 2, 3],
[4, 5, 6]]
#Нужно срезать до 1 индекса включительно у обоих и получить массив вида:
x = [[2, 3],
[5, 6]]
--------------------
x = [[1, 2, 3],
[4, 5, 6]]
#Нужно срезать до 2 индекса включительно у обоих и получить массив вида:
x = [[3],
[6]]
Не обращайте внимания на отступы, они сделаны для наглядности. Массивы в матрице всегда равны друг другу.
Моё решение
def cut(n: int, x: list[list]) -> list[list]:
new_massive = []
for i in range(len(x)):
massive = []
for j in range(n, len(x[0])):
massive.append(x[i][j])
new_massive.append(massive)
return new_massive
#Где n - это индекс, до которого нужно сразать. x - матрица.
Проблема
Моя функция работает за O(n^2). Как сделать её работу за O(n) и, если возможно, за O(1)?
Ответы (2 шт):
Автор решения: Алексей Р
→ Ссылка
Используйте срезы
def slice_n(matrix, n):
return [x[n:] for x in matrix]
x = [[1, 2, 3],
[4, 5, 6]]
print(slice_n(x, 1))
[[2, 3], [5, 6]]
Автор решения: extrn
→ Ссылка
Использовать массивы numpy вместо нативных списков.
import numpy as np
a = np.array([[1,2,3], [4,5,6]])
print(a[:, 1:])
print(a[:, 2:])
[[2 3]
[5 6]]
[[3]
[6]]
В них срезы бесплатные, потому, что ничего не копируют, а ссылаются на существующие данные
import timeit
a = np.random.random((10000, 10000))
print(timeit.timeit(lambda: a[:, 1:], number=1000000)) # 0.302562693999789
print(timeit.timeit(lambda: a[:, 9999:], number=1000000)) # 0.2967891000007512
a = np.random.random((10, 10))
print(timeit.timeit(lambda: a[:, 1:], number=1000000)) # 0.2955629850002879
print(timeit.timeit(lambda: a[:, 9:], number=1000000)) # 0.301412505999906
При любом копировании, будь то явном или срезами списков – сложность будет O(количество скопированных элементов), просто с разными скрытыми коэффициентами (срезы в разы быстрее).
import random
import timeit
a = random.sample(range(1000000), k=1000)
print(timeit.timeit(lambda: a[1:], number=1000000)) # 3.0076194629982638
print(timeit.timeit(lambda: a[999:], number=1000000)) # 0.23986860099830665