This is a clear explanation, but definitely still not the simplest. For me, the most straightforward method is to transpose the matrix and reverse each row. The code is simple and short. #transpose for row in range(len(matrix)): for col in range(row,len(matrix)): temp = matrix[row][col] matrix[row][col] = matrix[col][row] matrix[col][row] = temp #reverse for row in matrix: row.reverse() Accepted by leetcode.
excellent solution. By the way your solution is based on rotation matrix, right? For 90 degree, we have (x,y) -> (y,x) en.wikipedia.org/wiki/Rotation_matrix
I have another solution in similar vein. I came up with it by eyeballing the leetcode provided input/output samples and noticing that the firs element of the last row of the input is the first element of the first row of the output, the second element of the last row of the input is the first element of the second row of the output etc. thus n = len(matrix) for row in matrix[::-1]: for i in range(n): element = row.pop(0) matrix[i].append(element) also does the job ;)
This has been one of the toughest problems for me. Very hard to visualize and always used to make mistakes even after multiple attempts. The way that you explained the approach is THE BEST. You made it so crystal clear in visualizing the solution. Thank you so much!
I honestly think this is a Hard problem when it comes to implementation.. you can see the idea but coming up with the double pointer approach and a loop, thats a different story!
Thanks a lot for the content mate! No offence to others but I really like your clear accent and structured material which is easy to follow. Hope you keep up posting!
Although this is a good way to do it, I found my way to be a bit simpler once you understand matrix manipulation. Rotating a matrix by 90⁰ is equivalent to flipping the matrix diagonally and then flipping it vertically. First try it out with paper, and once u get it, it's really easy. It doesn't save runtime or anything, but I find it easier in terms of code than to move 4 things at a time layer by layer.
Brilliant idea. But this solution takes 2x time since you need to loop through the matrix twice. But the time complexity is still O(n) though. Good thinking!
@@jim5621 "This solution takes 2x time" isn't actually true. Because of things like cache locality, where the elements that are in the same row will be closer to operate on for the CPU, it's not possible to say that the element-wise method is faster. The profiling method actually worked about 25% faster from tests on my computer!
I gotta say your videos are amazing. I've been grinding LC for the past 3 weeks, I went from struggling to solve even 1 question on the weekly leetcode contest to solving 2 - 3 questions each week. Thank you so much. I've also and will always share your videos and excel sheet on reddit whenever people ask for leetcode tips. Oh and its abit late but congrats on the Google offer! I hope to one day get into google as well or any other company tbh ( my current tech job kinda blows ) ...
Great approach! Here you can see if you are confused with variable naming I have used some easy to understand names.Approach is still the same. void rotate(vector &matrix) { int size = matrix.size(); int startRow = 0; int startColumn = 0; int endRow = matrix.size() - 1; int endColumn = matrix.size() - 1; while (startRow < endRow && startColumn < endColumn) { int current_column_for_start_row = startColumn; int current_row_for_end_Column = startRow; int current_column_for_end_row = endColumn; int current_row_for_start_column = endRow; int current_size = endColumn - startColumn; for (int i = 0; i < current_size; i++) { int temp = matrix[startRow][current_column_for_start_row]; matrix[startRow][current_column_for_start_row] = matrix[current_row_for_start_column][startColumn]; matrix[current_row_for_start_column][startColumn] = matrix[endRow][current_column_for_end_row]; matrix[endRow][current_column_for_end_row] = matrix[current_row_for_end_Column][endColumn]; matrix[current_row_for_end_Column][endColumn] = temp; current_column_for_start_row++; current_row_for_end_Column++; current_column_for_end_row--; current_row_for_start_column--; } startRow++; startColumn++; endRow--; endColumn--; } }
Amazing solution and explanaition! I spent about 2 hours trying to understand leetcode "Rotate group of 4" solution - but no luck. Here 15 minutes - and it's clear.
I cant explain you how much this channel helps me !! Other channels just tell the transpose method which is not so intuitive, you always tell solutions which I can think in future in real interviews and exams. Thanks a lot Neetcode !! Keep up the good work man
Have been struggling with coming up with an notion of using boundaries and using that i variable. Neet explanations for the neet code to write. Thanks for adding this.
Great content Bro :) Solution in Java: class Solution { public void rotate(int[][] matrix) { int n = matrix.length; int right=n-1, left=0; //neetcode solution video while(left
@theraplounge because as you enter in the inner loops the offset, or the amout that you have to add/subtract for the rotation decreases. in the video for the outer matrix the offset can be as much as 2, but in the inner matrix that offset is 0.
Great explanation, however if you recalled from Linear Algebra, this is basically transpose the matrix so (row,col) becomes (col,row). So here's a shorter solution in Python rows = len(matrix) matrix.reverse() #Reverse the matrix for r in range(rows): for c in range(r,rows): matrix[r][c], matrix[c][r] = matrix[c][r], matrix[r][c] #Transpose
Your videos are excellent. You do a great job of being super clear! I often come here to Neetcode to see if you have the solution as it is better than the official explanation. Keep up the great work!
Easier solution for nXn matrix! Neetcode solution may be better suited for nXm matrix. function rotate(matrix: number[][]): void { const n = matrix.length; // Transpose the matrix, starting from i = 1 for (let i = 1; i < n; i++) { for (let j = i; j < n; j++) { [matrix[i][j], matrix[j][i]] = [matrix[j][i], matrix[i][j]]; } } // Reverse each row for (let i = 0; i < n; i++) { matrix[i].reverse(); } }
No doubt I love your simple algos but this one can be done in a much simpler way which is to reverse the matrix row wise and then swapping the elements like we do for a transpose. Kudos to the great work you do :)
But to do that you will have to create another matrix which is the copy of the Matrix which is to be transposed and that is against the constraints of the question you have to work in the same Matrix
There a very easy way to do this. First transpose the matrix, which is just flipping along a diagonal in-place. Then reflect vertically, which is another simple in-place swap.
I am thinking about the same. But the problem is we don't know if this is allowed, at least for the purpose of what this question is examining. If this is allowed then you can also use the 2D rotation matrix too.
Perfect Solution. When I first read the solution in the Cracking the coding interview book, I spent quite a lot of time and still could not understand it. You really simplified the logic which is so much easier to follow! Great Job, man
The guys talking about transpose mean this: Geometrically, rotation of the plane by 90 degrees is equivalent to flipping about the diagonal line y=-x and then flipping about the y-axis. That's why this works.
It's possible to do this without any extra memory at all. Suppose you have variables x and y. You can swap them like this y=y+x x=y-x y=y-x This is all you need to transpose a matrix and to swap columns or rows. This rotation is just a transposition followed by inverting the order of the rows.
You don't need 'top', 'bottom', 'left' and 'right' mambo jumbo! Simplified transformation for clockwise rotation of [ X, Y ] is: [ X, Y ] => [ Y, abs(X - len(matrix) - 1) ] ...and for counterclockwise: [ X, Y ] => [ abs(Y - len(matrix) - 1), X ] i.e. (switch coordinates and replace one with the absolute value of itself minus the length of the matrix minus 1) Do all transformations from [ 0, 0 ] using TEMP variable, then walk diagonally toward the center... [ 1, 1 ], [ 2, 2 ], ...
Just to point out: whenever you see a 2D, 3D or nD rotation or translation challenge, you know there is ONE rule that works for all the nodes. There are no special cases in rotation nor in translation. Always try to find the rule instead of breaking the matrix into small pieces -> i.e. more challenges.
Since its python you can just do def rotate(self, matrix: List[List[int]]) -> None: n = len(matrix) l, r = 0, n - 1 while l < r: top, bottom = l, r for i in range(r - l): ( matrix[top + i][r], matrix[top][l + i], matrix[bottom - i][l], matrix[bottom][r - i] ) = ( matrix[top][l + i], matrix[bottom - i][l], matrix[bottom][r - i], matrix[top + i][r] ) r -= 1 l += 1 So theres no need for a temp variable, in that case we also wouldnt have to care about doing it in reverse. But I think readablitiy suffers a little
An even better solution to consider: n = len(matrix) # Transpose Matrix for i in range(n): for j in range(i, n): matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j] # Reverse Matrix for row in matrix: row.reverse()
@@brainmaxxing1 Sure, but the TC of that solution is obviously much worse. For that solution theres no need for the second for loop either: n = len(matrix) for row in range(n): for col in range(row + 1, n): matrix[col][row], matrix[row][col] = matrix[row][col], matrix[col][row] matrix[row].reverse()
The time complexity of both solutions is the same, O(n^2). You do more 'operations' but the performance is actually better in my testing (somehow because of how the computer handles the more common operations of reversing a row and transposing a matrix) My notebook testing all 3 colab.research.google.com/drive/1laaMa1XLalAsShcoqENbbD5peb-PdCHo#scrollTo=QSThsieXZiCO Also nice on removing the second loop, that does speed it up.
I took a temp array, copied all columns into the rows of the temp array but in reverse order, finally, I iterated the temp array and replaced matrix[row] = temp_array[row]
You know you can just swap instead of using a temporary. Walk through it: Swap TL with TR Swap TL with BR Swap TL with BL Shazam, the corners are rotated and aux space is O(0).
@@trongthuong9581 There are two common methods and one other method that is CPU dependent: A) XOR swap: x ^= y y ^= x x ^= y B) Mathematical swap: x += y y = x - y x -= y C) x86 and x64 CPUs have the XCHG instruction, but it's likely to have the same performance as the other methods. Theoretically it would be faster since it can target a memory value directly, but doing so causes the CPU to lock all cores for synchronization, which is a massive performance hit. Operating just on registers, it has about 3 cycles of latency, which is similar to the XOR and mathematical methods.
Great explanation, does anyone know why the range has to be range(right- left) instead of range(left,right)? The range(left,right) works on many of the smaller test cases but does not work on many of the harder ones. Help!
hi neetcode, i have a question, how to rotate matrix 45 degrees so the matrix size will increase, i trying to make the solution and now i want to give up (i have tried straight 5 hours btw). Can you make this solution a video pls.
literally my go to channel..well was it really asked by microsoft?...I solved it by taking its transpose and then reversing it which is in place but needs two traversal
I found more two approaches to this, First one is to reverse the image and then transpose the resulting matrix (Easier). Other approach is to do this matrix[:] = zip(*matrix[::-1]) I don't really understand what's happening here so if someone understands, please do tell :) Thanks!
@@markvaldez526 range(l, r) doesn't work because we are iterating r - l times, not from l to r. For example, if l = 5, and r = 10, we need to run our for loop 5 times starting index from 0, 1, 2, 3, and 4 NOT from 5, 6, 7, 8, 9 which would be the case if we do range(5, 10).
Here is a js solution const rotate = (matrix) => { let left = 0; // number of columns - 1, // also think, actual position of right let right = matrix.length - 1; while (left < right) { for (let i = 0; i < right - left; i++) { let top = left; let bottom = right; let topLeft = matrix[top][left + i]; matrix[top][left + i] = matrix[bottom - i][left]; matrix[bottom - i][left] = matrix[bottom][right - i]; matrix[bottom][right - i] = matrix[top + i][right]; matrix[top + i][right] = topLeft; } left++; right--; } }; yes I know, py and JS are about as close to languages as you can get but for anyone new or may not understand the small differences between py and JS, here is your answer. NeetCode, thank you, your explanation was thorough and also less than 15 minutes which is great.
If the data set is n x n, the O(n) is for that n. Big O can be in terms of anything I think. I've seen O(mlogn) and other variables. If you say n x n = N, then yea O(N) is the time complexity.
To say this is time O(n^2) is subtly misleading/not best way to express the time complexity. While I understand that algebraically "n x n = n^2", when expressing the algo itself in time complexity, O(n^2) could be interpreted as a quadratic runtime. Since the algo only looks at each cell once, the algo is, in fact, linear, so it would be better to express "n x n" as just "M" and therefore O(M).
Chances are , you will not be able to think of a solution such as the second one (the one that stores only 1 variable). It's better to practise for the solution for the first one (the one that stores 4 different variables).
List2 = [] for x in range(len(matrix[0])): List1=[] for y in matrix[::-1]: list1.append(y[×]) List2.append(list1) return list2 Why this code is giving wrong output in leetcode but right output in local jupyter notebook
I find the standard rotation technique to be pretty frustrating to think about. Instead ive found its easier to invert the values on the diagonal then reverse the rows.
The explanation was awesome and helpful to understand the problem effectively. I was waiting to see the final input output but nevertheless the code is correct so i guess i will write and check myself 😁😊
Very well explained, but i spotted one line which could be shifted up. Line 10 can be put before the for loop isnt it ? no need to initialize it on every loop
I use JS. The same code but doesnt work! can't pass the case 6. I checked many times and asked GPT, GPT gave the correct answer, but leetcode didnt. Can anyone pass the case 6 with JS? var rotate = function (matrix) { let left = 0 let right = matrix.length - 1 while (left < right) { for (let i = left; i < right; i++) { let top = left let bottom = right const topLeft = matrix[top][left + i] matrix[top][left + i] = matrix[bottom - i][left] matrix[bottom - i][left] = matrix[bottom][right - i] matrix[bottom][right - i] = matrix[top + i][right] matrix[top + i][right] = topLeft } left++ right-- } };
Hi guys, does anyone know why the for loop (line 9) has to be range(right - left)? I thought range(left, right - 1) would work but I've tried it and it doesn't on the harder test cases. I can't wrap my head around why. Would appreciate any help.
The problem is that the indexing "breaks down" once 'left' gets increased. For the sample test cases, the size is smaller, like 3x3 or 4x4, and it passes there. If you're doing range(left, right - 1) that makes i = left, left + 1, left + 2 instead of 0, 1, 2. It means you'd need to change your calls like matrix[top][left+i] should instead be matrix[top][i] and the calls like matrix[bottom-i][left] should instead be matrix[bottom-i+left][left]. The full code: class Solution: def rotate(self, matrix: List[List[int]]) -> None: """ Do not return anything, modify matrix in-place instead. """ n = len(matrix) left, right = 0, n - 1 while left
Hey. Thank you for the explanation. Query: In your drawing, you portray the bottom pointer moving up and the top pointer moving down, so it's kinda confusing for me because in your code you write 'bottom - i' and 'top + i'. Mind explaining this distinction?