Transpose Matrix
Otrzymujesz macierz liczb całkowitych w postaci listy wierszy: matrix[i][j] to wartość w wierszu i, kolumnie j. Zwróć jej transpozycję: wartość z wiersza i, kolumny j przenosi się do wiersza j, kolumny i, tak aby każdy wiersz stał się kolumną. Macierz nie musi być kwadratowa: macierz m × n staje się macierzą n × m.
Funkcja
- matrixinteger-2d-array
- macierz m × n jako lista m wierszy zawierających n liczb całkowitych
- Zwracainteger-2d-array
- transpozycja o wymiarach n × m, jako lista n wierszy po m liczb całkowitych
Ograniczenia
1 ≤ m, n ≤ 1000, gdziem = matrix.lengthin = matrix[i].lengthm × n ≤ 5000- Każdy wiersz ma tę samą długość
n. -1000 ≤ matrix[i][j] ≤ 1000
Przykłady
- Wejście
- matrix = [[1, 2, 3], [4, 5, 6]]
- Wyjście
- [[1, 4], [2, 5], [3, 6]]
- Wyjaśnienie
- Wiersz
[1, 2, 3]staje się pierwszą kolumną, a[4, 5, 6]drugą. Odczytując wiersz po wierszu, otrzymujemy[1, 4],[2, 5],[3, 6]: macierz 3 × 2.
- Wejście
- matrix = [[1, 2], [3, 4]]
- Wyjście
- [[1, 3], [2, 4]]
- Wyjaśnienie
- Wartości na przekątnej, 1 i 4, pozostają na swoim miejscu. Dwie pozostałe zamieniają się miejscami: 2 przenosi się z wiersza 0, kolumny 1 do wiersza 1, kolumny 0, a 3 przemieszcza się w przeciwnym kierunku.
Pytanie dodatkowe
Załóżmy, że macierz jest przechowywana jako jedna płaska tablica wartości m × n, wiersz po wierszu. Czy potrafisz transponować macierz niekwadratową w tej tablicy, bez użycia drugiej tablicy?
Podpowiedzi
Otwieraj je po kolei. Każda zdradza trochę więcej.
Jeśli dane wejściowe mają
mwierszy inkolumn, ile wierszy i kolumn ma wynik?Porównaj, gdzie znajduje się wartość przed i po: wartość z wiersza
i, kolumnyjtrafia do wierszaj, kolumnyi.Utwórz wynik z
nwierszy, z których każdy zawieramwartości, a następnie przejdź pętlą po każdej komórce danych wejściowych i skopiujmatrix[i][j]doresult[j][i].
Rozwiązanie
Transponowanie niczego nie oblicza: wartość z pozycji (i, j) przenosi się na pozycję (j, i). Zmienia się kształt. Wynik ma n wierszy o długości m, więc nieskwadratowej listy wierszy nie można transponować w miejscu; utwórz nową macierz o zamienionych wymiarach i wypełnij ją.
Czytaj macierz kolumna po kolumnie
Intuicja
Wiersz j wyniku to kolumna j danych wejściowych, odczytywana od góry do dołu. Dla [[1, 2, 3], [4, 5, 6]] kolumna 0 zawiera kolejno 1 i 4, więc pierwszy wiersz wyniku to [1, 4].
Każda wartość jest odczytywana raz i zapisywana raz: czas O(m × n) i O(m × n) miejsca na wynik. Podczas budowania każdego nowego wiersza przeskakujesz przez wszystkie wiersze danych wejściowych, zamiast odczytywać wartości wzdłuż jednego wiersza — to wolniejszy sposób przeglądania pamięci.
Algorytm
- Niech
moznacza liczbę wierszy, andługość wiersza. - Dla każdej kolumny
jod0don-1rozpocznij od pustej listy. - Dodaj do niej
matrix[i][j]dla każdegoiod0dom-1. - Dodaj listę do wyniku jako wiersz
ji zwróć wynik po ostatniej kolumnie.
def transpose(matrix):
m, n = len(matrix), len(matrix[0])
result = []
for j in range(n):
# Column j, read top to bottom, becomes row j of the answer.
column = []
for i in range(m):
column.append(matrix[i][j])
result.append(column)
return resultWypełnij nową siatkę n × m, odbijając lustrzanie każdą komórkę
Intuicja
Utwórz z góry wynik o rozmiarze n × m, a następnie odczytuj dane wejściowe w kolejności, w jakiej są zapisane, wiersz po wierszu, i umieszczaj każdą wartość pod jej lustrzanym adresem: result[j][i] = matrix[i][j]. To poprawne, ponieważ transpozycja polega dokładnie na zamianie tych indeksów, wykonanej raz dla każdej komórki.
Każda wartość jest kopiowana raz, więc złożoność czasowa wynosi O(m × n), a siatka zajmuje O(m × n) miejsca, którego wynik i tak potrzebuje. Odczytywanie wierszami odwiedza pamięć w zapisanej kolejności, a każdy wiersz wyniku jest alokowany raz, od razu w docelowym rozmiarze.
Algorytm
- Niech
moznacza liczbę wierszy, andługość wiersza. - Utwórz
resultznwierszami, z których każdy zawieramwartości. - Dla każdego wiersza
ii każdej kolumnyjdanych wejściowych ustawresult[j][i] = matrix[i][j]. - Zwróć
result.
def transpose(matrix):
m, n = len(matrix), len(matrix[0])
# The answer has n rows of m values each.
result = [[0] * m for _ in range(n)]
for i in range(m):
for j in range(n):
result[j][i] = matrix[i][j]
return result
Pułapki i przypadki brzegowe
- Tworzenie wyniku o kształcie takim jak dane wejściowe. W przykładzie 2 × 3 zapisanie
result[2][0]wykracza poza koniec: wynik potrzebujenwierszy o długościm. - Zamiana miejscami
matrix[i][j]imatrix[j][i]w miejscu. Działa to tylko wtedy, gdym = n, i tylko dla komórek, w którychj > i; pętla przechodząca przez każdą komórkę zamienia każdą parę dwa razy i zwraca niezmienioną macierz. - W Pythonie
[[0] * m] * ntworzynodwołań do jednej listy, więc zapisanie wartości w jednej komórce zmienia całą kolumnę. Twórz każdy wiersz osobno. - W C funkcja wywołująca odczytuje
*returnSizejako liczbę wierszy wyniku,n, a(*returnColumnSizes)[j]jako długość każdego wiersza,m.
Najczęstsze pytania3
Co to jest transpozycja macierzy?
To macierz, którą otrzymujesz przez zamianę wierszy na kolumny: wartość w wierszu i, kolumnie j przenosi się do wiersza j, kolumny i. Macierz 2 × 3 staje się macierzą 3 × 2, a dwukrotna transpozycja daje z powrotem macierz wyjściową.
Jaka jest złożoność czasowa transponowania macierzy?
O(m × n): każda z m × n wartości jest kopiowana raz i nic mniej nie pozwoli uzyskać odpowiedzi. Nowa macierz zajmuje O(m × n) pamięci, tyle, ile wynosi rozmiar samego wyniku.
Czy możesz transponować macierz w miejscu?
W przypadku macierzy kwadratowej tak: zamień miejscami matrix[i][j] i matrix[j][i] dla każdej komórki powyżej przekątnej, używając dodatkowo O(1) pamięci. Macierz niekwadratowa zmienia kształt, więc w przypadku listy wierszy potrzebujesz nowej macierzy.
Podobne zadania
Zadania oparte na tych samych pomysłach. Rozwiązanie dwóch lub trzech utrwala schemat.
def transpose(matrix):
# Wpisz kod tutajTest #1
Test #2
Argument
matrix = [[1, 2, 3], [4, 5, 6]]
Oczekiwany wynik
[[1, 4], [2, 5], [3, 6]]