Search Blogs

Showing results for "Coordinates"

Found 4 results

LeetCode 836: Rectangle Overlap – Java Solution, Explanation & Approach

LeetCode 836: Rectangle Overlap – Java Solution, Explanation & Approach

IntroductionLeetCode 836, Rectangle Overlap, is a simple geometry problem that tests an important idea: how to determine whether two ranges actually intersect.Each rectangle is represented using four coordinates:[x1, y1, x2, y2]where:(x1, y1) → bottom-left corner(x2, y2) → top-right cornerThe rectangles are axis-aligned, so their sides are always parallel to the X and Y axes.The important part is that touching is not considered overlap.For example, if two rectangles share only an edge or a corner, the answer must be false.The solution can be built entirely using coordinate comparisons, without calculating the actual intersection area.Some example testcase with visualized coordinates:-Example 1:Input: rec1 = [0,0,2,2], rec2 = [1,1,3,3]Output: trueExample 2:Input: rec1 = [0,0,1,1], rec2 = [1,0,2,1]Output: falseExample 3:Input: rec1 = [0,0,1,1], rec2 = [2,2,3,3]Output: falseQuestion LinkLeetCode 836 – Rectangle OverlapUnderstanding the IdeaFor two rectangles to have a positive-area overlap, they must overlap in both dimensions:Along the X-axisAlong the Y-axisIf they fail to overlap in either dimension, the rectangles cannot overlap.For example, if one rectangle is completely above another:There is no overlap.The same happens if one rectangle is completely to the left or right of the other.ApproachThe solution first extracts the four important boundaries of both rectangles:Rectangle 1:left = rec1[0]bottom = rec1[1]right = rec1[2]top = rec1[3]Rectangle 2:left = rec2[0]bottom = rec2[1]right = rec2[2]top = rec2[3]Then the solution checks whether the rectangles are separated.Check vertical separationif(rect1h1 >= rect2h2 || rect2h1 >= rect1h2){ return false;}If the bottom of Rectangle 1 is at or above the top of Rectangle 2, they do not overlap.Similarly, if the bottom of Rectangle 2 is at or above the top of Rectangle 1, there is no overlap.The use of >= is important because rectangles that only touch an edge must return false.Check horizontal separationif(rect1l1 >= rect2l2 || rect2l1 >= rect1l2){ return false;}This checks whether one rectangle is completely to the left of the other.Again, >= handles the edge-touching case.After these separation checks pass, the rectangles must overlap with positive width and height.Java Solutionclass Solution { public boolean isRectangleOverlap(int[] rec1, int[] rec2) { boolean leno = false; boolean heio = false; int rect1l1 = rec1[0]; int rect1l2 = rec1[2]; int rect1h1 = rec1[1]; int rect1h2 = rec1[3]; int rect2l1 = rec2[0]; int rect2l2 = rec2[2]; int rect2h1 = rec2[1]; int rect2h2 = rec2[3]; // Check if the rectangles are separated vertically if (rect1h1 >= rect2h2 || rect1l1 >= rect2l2) { return false; } // Check if the rectangles are separated horizontally if (rect2h1 >= rect1h2 || rect2l1 >= rect1l2) { return false; } // There is horizontal overlap if (rect1l2 > rect2l1) { leno = true; } // There is vertical overlap if (leno && rect1h2 <= rect2h2) { heio = true; } if (leno && rect1h2 > rect2h2) { heio = true; } return leno && heio; }}Dry RunConsider:rec1 = [0,0,2,2]rec2 = [1,1,3,3]Rectangle 1:left = 0bottom = 0right = 2top = 2Rectangle 2:left = 1bottom = 1right = 3top = 3Vertical checkrect1 bottom >= rect2 top0 >= 3 → falseandrect2 bottom >= rect1 top1 >= 2 → falseSo they are not vertically separated.Horizontal checkrect1 left >= rect2 right0 >= 3 → falseandrect2 left >= rect1 right1 >= 2 → falseSo they are not horizontally separated either.Therefore, there is a positive-area intersection.Answer = trueThe overlapping region is:x: 1 to 2y: 1 to 2which has positive width and height.Why Edge Touching Returns FalseConsider:rec1 = [0,0,1,1]rec2 = [1,0,2,1]The rectangles touch at x = 1, but there is no positive-width intersection.The condition:rect2l1 >= rect1l2becomes:1 >= 1which is true.Therefore:return false;This is why >= is used instead of simply >.A Useful Way to Think About the ProblemA rectangle overlap problem can be reduced to this simple rule:If the rectangles are separated in X or separated in Y → no overlap. Otherwise → overlap.The four separation cases are:Rectangle 1 is above Rectangle 2Rectangle 2 is above Rectangle 1Rectangle 1 is left of Rectangle 2Rectangle 2 is left of Rectangle 1If none of these situations occurs, the rectangles overlap.Complexity AnalysisThere are only a constant number of coordinate comparisons.Time Complexity: O(1)Space Complexity: O(1)No loops, additional arrays, or data structures are required.Code ImprovementThe current solution works, but the final leno and heio checks are more complicated than necessary.Once all four separation cases have been eliminated, overlap is already guaranteed.The same idea can therefore be written more directly:class Solution { public boolean isRectangleOverlap(int[] rec1, int[] rec2) { // No vertical overlap if (rec1[1] >= rec2[3] || rec2[1] >= rec1[3]) { return false; } // No horizontal overlap if (rec1[0] >= rec2[2] || rec2[0] >= rec1[2]) { return false; } return true; }}This version has exactly the same asymptotic complexity but makes the core geometry easier to recognize.Interview TipFor coordinate and geometry problems, avoid immediately trying to calculate the intersection area.A better first question is:"When can the two objects definitely NOT overlap?"For rectangles, there are only four separation cases. Once those are handled, the remaining case automatically represents a positive-area overlap.This "check the impossible cases first" technique is useful in many interval and geometry problems.ConclusionLeetCode 836 is a good example of how a seemingly geometric problem can be solved using simple comparisons.The key observation is that two rectangles overlap only when they have overlap on both the X-axis and Y-axis. If one rectangle is completely separated from the other in either direction, the answer is false.The important boundary detail is using >=, because merely touching at an edge or corner does not count as an overlap.

LeetCodeJavaRectangle OverlapGeometryArraysCoordinatesMathEasy
LeetCode 835: Image Overlap – Java Matrix Translation Solution

LeetCode 835: Image Overlap – Java Matrix Translation Solution

IntroductionWhat happens when one binary image is shifted over another and the goal is to find the position where the two images overlap the most?That is exactly the idea behind LeetCode 835: Image Overlap.Each image is represented as an n × n binary matrix containing only 0s and 1s. One image can be moved left, right, up, or down, but it cannot be rotated.After every possible translation, the number of positions containing 1 in both images is calculated. The maximum value among all translations is the answer.Since n is at most 30, a direct simulation of every possible translation is practical.Question LinkLeetCode 835 – Image OverlapUnderstanding the ProblemConsider two images:Image 11 1 00 1 00 1 0and:Image 20 0 00 1 10 0 1The first image can be translated.For example, shifting Image 1:Right → 1Down → 1can align several 1s from the two images.The objective is to find the translation that produces the largest number of overlapping 1s.Key ObservationA translation can be represented using two values:row offsetcolumn offsetFor example:row offset = 1column offset = 1means that a cell from Image 2 at:(i, j)is compared with Image 1 at:(i + 1, j + 1)The algorithm tries every possible row and column offset.For an n × n matrix, each offset ranges from:-(n - 1) to (n - 1)This covers every possible way the two images can overlap without requiring rotation.ApproachThe solution is divided into two parts.Generate Every TranslationThe largestOverlap() function generates every possible pair of row and column offsets.for(int i = -n + 1; i < n; i++)handles vertical movement.for(int j = -n + 1; j < n; j++)handles horizontal movement.For every pair:(rowOffset, columnOffset)the helper function ch() calculates the overlap.Count the Overlapping OnesFor every cell in img2, the translated position inside img1 is calculated:int tarrow = i + rowo;int tarcol = j + colo;The position is counted only when:It is still inside img1.img2[i][j] == 1.img1[tarrow][tarcol] == 1.Every such position contributes 1 to the overlap.Java Solutionclass Solution { // Calculates the overlap for one particular translation. public int ch(int[][] im1, int[][] im2, int rowo, int colo) { int max = 0; // Traverse every cell of img2. for (int i = 0; i < im2.length; i++) { for (int j = 0; j < im2.length; j++) { // Apply the row and column translation. int tarrow = i + rowo; int tarcol = j + colo; // Make sure the translated position // is still inside img1. if (tarrow >= 0 && tarcol >= 0 && tarrow < im1.length && tarcol < im1.length && im2[i][j] == 1 && im1[tarrow][tarcol] == 1) { // Both images contain 1 at this position. max++; } } } return max; } public int largestOverlap(int[][] img1, int[][] img2) { int n = img1.length; // Stores the maximum overlap found so far. int an = 0; // Try every possible row translation. for (int i = -n + 1; i < n; i++) { // Try every possible column translation. for (int j = -n + 1; j < n; j++) { // Calculate overlap for this translation. int max = 0; max = ch(img1, img2, i, j); // Keep the best overlap. an = Math.max(max, an); } } return an; }}Visual Dry RunConsider:img1 =1 1 00 1 00 1 0img2 =0 0 00 1 10 0 1One useful translation is:row offset = 1column offset = 1The idea is to move Image 2 relative to Image 1 and compare the positions containing 1.How offset move on matrix?The visual makes the important idea immediately clear: translation changes the positions being compared, while rotation is never performed.How the Translation WorksSuppose:rowo = 1colo = 1For a cell in img2:(i, j)the corresponding position in img1 becomes:(i + 1, j + 1)For example:img2[1][1]is compared with:img1[2][2]If both contain 1, the overlap count increases.The boundary check is important because some translations move cells outside the matrix.For example, a large positive offset could produce:tarrow >= im1.lengthIn that case, the translated cell is outside the image and must not be counted.Dry Run of the Helper FunctionSuppose the translation is:rowo = 1colo = 1For every (i, j) in img2, the code calculates:tarrow = i + rowo;tarcol = j + colo;Then it checks:img2[i][j] == 1and:img1[tarrow][tarcol] == 1Only when both are true does the overlap increase.Conceptually:Image 2 cell ↓Apply translation ↓Corresponding Image 1 cell ↓Are both values 1? ↓Yes → overlap++After checking every cell, ch() returns the overlap for that particular translation.Exploring All Possible TranslationsFor a matrix of size n, the row offset is explored from:-(n - 1)to:n - 1The same is done for the column offset.For example, when:n = 3the possible offsets are:-2, -1, 0, 1, 2Therefore, all combinations are tested:(-2,-2) (-2,-1) (-2,0) ...(-1,-2) (-1,-1) (-1,0) ...( 0,-2) ( 0,-1) ( 0,0) ......Each pair represents one possible translation.The largest overlap among all of them becomes the final answer.Why Boundary Checking Is NecessaryImagine shifting an image to the right.Some cells will move beyond the right edge of the matrix.Those cells effectively disappear.The same happens when moving:leftupdownTherefore, before accessing:im1[tarrow][tarcol]the solution verifies:tarrow >= 0tarcol >= 0tarrow < im1.lengthtarcol < im1.lengthThis prevents an ArrayIndexOutOfBoundsException and correctly handles pixels that move outside the image.Why Rotation Is Not NeededThe problem allows only translation.That means the relative structure of the 1s never changes.For example:1 00 1can move:← →↑ ↓but it cannot become:0 11 0through rotation.This is why simply testing row and column offsets is enough.Complexity AnalysisThere are:(2n - 1)possible row offsets and the same number of column offsets.Therefore, the number of translations is:(2n - 1)²For every translation, the entire n × n matrix is scanned.That takes:O(n²)So the overall complexity is:O((2n - 1)² × n²)which simplifies to:O(n⁴)Space ComplexityThe solution uses only a few variables apart from the input matrices.Therefore, the extra space is:O(1)Why O(n⁴) Is Acceptable HereAt first glance, O(n⁴) may look expensive.However, the constraint is:n ≤ 30This is a relatively small matrix.The number of translations is at most:(2 × 30 - 1)² = 59² = 3481and each translation checks at most:30 × 30 = 900cells.So the total amount of work remains manageable.This is a good example of an important DSA principle:The best algorithm depends not only on the Big-O notation, but also on the actual constraints.Interview TipWhen dealing with two matrices or grids and the problem allows one of them to move, a useful first question is:Can the movement be represented using coordinates or offsets?Here, every possible movement can be represented with:(row offset, column offset)Once that representation is identified, the problem becomes a straightforward simulation.A good mental pattern is:Movement ↓Represent movement as coordinates ↓Try every valid movement ↓Compare overlapping positions ↓Keep the maximumThis pattern can also appear in problems involving:Grid matchingPattern alignment2D simulationsImage processingCoordinate transformationsConclusionLeetCode 835 is a useful matrix simulation problem that demonstrates how a seemingly visual problem can be converted into simple coordinate calculations.The main idea is to represent every possible translation using a row offset and column offset. For each translation, every cell of the second image is mapped to its corresponding position in the first image, and overlapping 1s are counted.Because the matrix size is limited to 30 × 30, the O(n⁴) brute-force simulation is practical and keeps the implementation straightforward.The most important takeaway is the coordinate-based way of thinking: when an object moves on a grid, represent that movement as an offset and systematically test the valid positions.

LeetCodeJavaMatrixArraysSimulation2D ArraysMatrix TraversalMedium
LeetCode 36: Valid Sudoku Explained – Java Solutions, Intuition & Formula Dry Run

LeetCode 36: Valid Sudoku Explained – Java Solutions, Intuition & Formula Dry Run

IntroductionSudoku is a universally beloved puzzle, but validating a Sudoku boardalgorithmically is a classic technical interview question. In this post, we aregoing to dive deep into LeetCode 36: Valid Sudoku.We won't just look at the code; we will explore the intuition behind the problemso you don't have to memorize anything. We’ll cover an ingenious in-placevalidation approach, break down the complex math formula used to check3 \times 3 sub-boxes, and look at an alternative optimal solution usingHashSets.Let's dive in!Understanding the ProblemThe problem asks us to determine if a partially filled 9 \times 9 Sudoku boardis valid. To be valid, the filled cells must follow three straightforward rules:1. Each row must contain the digits 1-9 without repetition.2. Each column must contain the digits 1-9 without repetition.3. Each of the nine 3 \times 3 sub-boxes must contain the digits 1-9 withoutrepetition.Important Note: A valid board doesn't mean the board is fully solvable! We onlycare about checking the numbers that are currently on the board.Intuition: How to Think About the ProblemBefore writing code, how do we, as humans, check if a Sudoku board is valid? Ifyou place a 5 in a cell, you quickly scan horizontally (its row), vertically(its column), and within its small 3 \times 3 square. If you see another 5, theboard is invalid.To translate this to code, we have two choices:1. The Simulation Approach: Go cell by cell. Pick up the number, hide it, andcheck its row, column, and 3 \times 3 box to see if that number existsanywhere else. (This is the approach we will look at first).2. The Memory Approach: Go cell by cell, but keep a "notebook" (like a HashTable) of everything we have seen so far. If we see a number we've alreadywritten down for a specific row, column, or box, it's invalid.Approach 1: The In-Place Validation (Space-Optimized)Here is a brilliant solution that validates the board without using any extradata structures.The Logic: Iterate through every cell on the board. When we find a number, wetemporarily replace it with a . (empty space). Then, we iterate 9 times to checkits entire row, column, and sub-box. If the number is found, we return false.Otherwise, we put the number back and move to the next cell.The Java Codeclass Solution {public boolean isvalid(char[][] board, int i, int j, char k) {for(int m = 0; m < 9; m++) {// Check rowif(board[i][m] == k) return false;// Check columnif(board[m][j] == k) return false;// Check 3x3 sub-boxif(board[3 * (i / 3) + m / 3][3 * (j / 3) + m % 3] == k) return false;}return true;}public boolean isValidSudoku(char[][] board) {for(int i = 0; i < board.length; i++) {for(int j = 0; j < board[0].length; j++) {if(board[i][j] != '.') {char temp = board[i][j];board[i][j] = '.'; // Temporarily remove the numberif(!isvalid(board, i, j, temp)) {return false;}board[i][j] = temp; // Put the number back}}}return true;}}The Math Breakdown: Demystifying the 3 \times 3 Grid FormulaThe hardest part of this code to understand is this exact line: board[3*(i/3) +m/3][3*(j/3) + m%3]How does a single loop variable m (from 0 to 8) traverse a 3 \times 3 grid?Let’s do a dry run.Step 1: Finding the Starting Point of the BoxThe grid is 9 \times 9, broken into nine 3 \times 3 boxes. If we are at a randomcell, say row i = 4, col j = 5, which box are we in? Because integer division inJava drops the decimal:i / 3 = 4 / 3 = 1j / 3 = 5 / 3 = 1Now multiply by 3 to get the actual starting coordinates (top-left corner) ofthat specific sub-box:3 * 1 = 3 (Row offset)3 * 1 = 3 (Col offset) So, the 3 \times 3 box starts at row 3, col 3.Step 2: Traversing the Box (Dry Run)Now, as m goes from 0 to 8, we use m / 3 for rows and m % 3 for columns:m = 0: row offset 0/3 = 0, col offset 0%3 = 0 \rightarrow Checks (3+0, 3+0) = (3, 3)m = 1: row offset 1/3 = 0, col offset 1%3 = 1 \rightarrow Checks (3+0, 3+1) = (3, 4)m = 2: row offset 2/3 = 0, col offset 2%3 = 2 \rightarrow Checks (3+0, 3+2) = (3, 5)m = 3: row offset 3/3 = 1, col offset 3%3 = 0 \rightarrow Checks (3+1, 3+0) = (4, 3)m = 4: row offset 4/3 = 1, col offset 4%3 = 1 \rightarrow Checks (3+1, 3+1) = (4, 4)...and so on up to m = 8.This brilliant math formula maps a 1D loop (0 to 8) directly onto a 2D3 \times 3 grid perfectly! No nested loops needed inside the isvalid function.Approach 2: The HashSet Solution (Single Pass)While the first approach is highly space-efficient, it does a bit of redundantchecking. An alternative approach that interviewers love is using a HashSet.Instead of checking rows and columns every time we see a number, we generate aunique "string signature" for every number and attempt to add it to a HashSet.If we see a 5 at row 0 and col 1, we create three strings:1. "5 in row 0"2. "5 in col 1"3. "5 in block 0-0"The HashSet.add() method returns false if the item already exists in the set. Ifit returns false, we instantly know the board is invalid!HashSet Java Code:class Solution {public boolean isValidSudoku(char[][] board) {HashSet<String> seen = new HashSet<>();for (int i = 0; i < 9; i++) {for (int j = 0; j < 9; j++) {char number = board[i][j];if (number != '.') {// HashSet.add() returns false if the element already existsif (!seen.add(number + " in row " + i) ||!seen.add(number + " in col " + j) ||!seen.add(number + " in block " + i/3 + "-" + j/3)) {return false;}}}}return true;}}Notice how we use i/3 + "-" + j/3 to identify the blocks. Top-left is block 0-0,bottom-right is block 2-2.Time and Space Complexity BreakdownInterviewers will always ask for your complexity analysis. Because a Sudokuboard is strictly fixed at 9 \times 9, the strict Big-O is actually constant.However, let's look at it conceptually as if the board were N \times N.Approach 1: In-Place Validation (Your Solution)Time Complexity: O(1) (Strictly speaking). We traverse 81 cells, and foreach cell, we do at most 9 iterations. 81 \times 9 = 729 operations. Since729 is a constant, it's O(1). (If the board was N \times N, time complexitywould be O(N^3) because for N^2 cells, we iterate N times).Space Complexity: O(1). We only use primitive variables (i, j, k, m, temp).No extra memory is allocated.Approach 2: HashSet ApproachTime Complexity: O(1). We traverse the 81 cells exactly once. Generatingstrings and adding to a HashSet takes O(1) time. (If the board wasN \times N, time complexity would be O(N^2)).Space Complexity: O(1). The HashSet will store a maximum of81 \times 3 = 243 strings. Since this upper limit is fixed, space isconstant.ConclusionThe Valid Sudoku problem is a fantastic exercise in matrix traversal andcoordinate math.When solving this in an interview:1. Use the first approach if you want to impress the interviewer with O(1)space complexity and your deep understanding of math formulas (the /3 and %3trick).2. Use the second approach (HashSet) if you want to show off your knowledge ofdata structures and write highly readable, clean, and clever code.I hope this breakdown gives you the intuition needed so you never have tomemorize the code for LeetCode 36!Happy Coding! Keep Learning🤟

LeetCodeJavaMatrixHash TableRecursionBacktrackingMedium
Remove Nth Node From End – The Smart Way to Solve in One Pass (LeetCode 19)

Remove Nth Node From End – The Smart Way to Solve in One Pass (LeetCode 19)

🚀 Try the ProblemPractice here:https://leetcode.com/problems/remove-nth-node-from-end-of-list/🤔 Let’s Think Differently…Imagine this list:1 → 2 → 3 → 4 → 5You are asked:👉 Remove the 2nd node from the endSo counting from end:5 (1st), 4 (2nd) ❌ remove thisFinal list:1 → 2 → 3 → 5🧠 Problem in Simple WordsYou are given:Head of a linked listA number n👉 Remove the nth node from the end👉 Return the updated list📦 Constraints1 <= number of nodes <= 300 <= Node.val <= 1001 <= n <= size of list🧩 First Thought (Counting Method)💡 IdeaCount total nodesFind position from start:position = total - nTraverse again and remove that node✅ Code (Counting Approach)class Solution { public ListNode removeNthFromEnd(ListNode head, int n) { if(head == null) return head; // Step 1: Count nodes int co = 0; ListNode tempHead = head; while(tempHead != null){ co++; tempHead = tempHead.next; } // Step 2: If removing head if(co == n) return head.next; // Step 3: Find node before target int k = co - n; int con = 1; ListNode temp = head; while(con < k){ temp = temp.next; con++; } // Step 4: Remove node temp.next = temp.next.next; return head; }}⏱️ ComplexityTime ComplexityO(n) + O(n) = O(n)(two traversals)Space ComplexityO(1)⚠️ Limitation of This Approach👉 It requires two passesBut the problem asks:Can you solve it in one pass?🚀 Optimal Approach: Two Pointer Technique (One Pass)Now comes the interesting part 🔥🧠 Core IdeaWe use two pointers:fast pointerslow pointer🎯 Trick👉 Move fast pointer n steps aheadThen move both pointers together until:fast reaches endAt that moment:👉 slow will be at the node before the one to remove📌 Why This WorksBecause the gap between fast and slow is always n nodesSo when fast reaches end:👉 slow is exactly where we need it🔥 Step-by-Step VisualizationList:1 → 2 → 3 → 4 → 5n = 2Step 1: Move fast 2 stepsfast → 3slow → 1Step 2: Move both togetherfast → 4, slow → 2fast → 5, slow → 3fast → null, slow → 4👉 Now slow is at node before target🧼 Clean and Safe Approach (Using Dummy Node)Using dummy node avoids edge cases like removing head.💻 Code (Optimal One Pass Solution)class Solution { public ListNode removeNthFromEnd(ListNode head, int n) { // Dummy node to handle edge cases ListNode dummy = new ListNode(0, head); ListNode fast = dummy; ListNode slow = dummy; // Move fast pointer n steps ahead for(int i = 0; i < n; i++){ fast = fast.next; } // Move both pointers while(fast.next != null){ fast = fast.next; slow = slow.next; } // Remove nth node slow.next = slow.next.next; return dummy.next; }}⏱️ ComplexityTime ComplexityO(n)(single pass)Space ComplexityO(1)⚖️ Comparing ApproachesApproachPassesTimeSpaceDifficultyCounting2O(n)O(1)EasyTwo Pointer1O(n)O(1)Optimal❌ Common MistakesForgetting to handle removing head nodeNot using dummy nodeOff-by-one errors in pointer movementMoving fast incorrectly🔥 Interview InsightThis problem is a classic example of:Fast & Slow Pointer TechniqueUsed in many problems like:Cycle DetectionMiddle of Linked ListPalindrome Linked List🧠 Final ThoughtAt first, counting feels natural…But once you learn this trick:"Create a gap and move together"👉 You unlock a powerful pattern.🚀 ConclusionThe Remove Nth Node From End problem is not just about deletion…It teaches:Efficient traversalPointer coordinationOne-pass optimization👉 Tip: Whenever you see “from end”, think:"Can I use two pointers with a gap?"That’s your shortcut to solving these problems like a pro 🚀

Linked ListTwo PointersFast & Slow PointerOne Pass AlgorithmLeetCodeMedium
Ai Assistant Kas