diff --git a/Problem1.java b/Problem1.java new file mode 100644 index 00000000..b0277a17 --- /dev/null +++ b/Problem1.java @@ -0,0 +1,51 @@ +//We use a HashSet to track numbers present in the array. + +//Steps: +//1.Add all elements into HashSet +//2.Check numbers from 1 to n +//3.If number is missing in set → add to result + +//Time: O(n) +//Space: O(n) + +class Solution { + + public List findDisappearedNumbers(int[] nums) { + + // List to store missing numbers + List result = new ArrayList<>(); + + // HashSet to store all present numbers + HashSet set = new HashSet<>(); + + // Length of array + int n = nums.length; + + + + // Step 1: Add all numbers from array into HashSet + // This helps in fast lookup O(1) + for(int i = 0; i < n; i++) { + + set.add(nums[i]); + } + + + + // Step 2: Check numbers from 1 to n + for(int i = 1; i <= n; i++) { + + // If number is not present in set + // then it is missing + if(!set.contains(i)) { + + result.add(i); + } + } + + + + // Return missing numbers list + return result; + } +} \ No newline at end of file diff --git a/Problem2.java b/Problem2.java new file mode 100644 index 00000000..1357c16a --- /dev/null +++ b/Problem2.java @@ -0,0 +1,90 @@ +//This is the efficient pair comparison method to find minimum and maximum. +// +//Instead of comparing every element with min and max separately, we: +//Compare elements in pairs +//First compare pair internally +//Then compare with global min and max +//Time: O(n) +//Space: O(1) + +public class Problem2 { + + public int[] findMinAndMax(int[] nums) { + + // Length of array + int n = nums.length; + + // Variables to store minimum and maximum + int min, max; + + // Index to start processing + int i; + + + // STEP 1: Handle first pair separately + + // If number of elements is EVEN + if (n % 2 == 0) { + + // Compare first two elements + if (nums[0] < nums[1]) { + + min = nums[0]; + max = nums[1]; + + } else { + + min = nums[1]; + max = nums[0]; + } + + // Start checking from index 2 + i = 2; + } + + // If number of elements is ODD + else { + + // Initialize both min and max with first element + min = nums[0]; + max = nums[0]; + + // Start checking from index 1 + i = 1; + } + + + + // STEP 2: Process remaining elements in PAIRS + + while (i < n - 1) { + + // First compare elements within pair + if (nums[i] < nums[i + 1]) { + + // Compare smaller with current min + min = Math.min(min, nums[i]); + + // Compare larger with current max + max = Math.max(max, nums[i + 1]); + } + + else { + + // Compare smaller with current min + min = Math.min(min, nums[i + 1]); + + // Compare larger with current max + max = Math.max(max, nums[i]); + } + + // Move to next pair + i += 2; + } + + + + // Return result as array: [min, max] + return new int[]{min, max}; + } +} \ No newline at end of file diff --git a/Problem3.java b/Problem3.java new file mode 100644 index 00000000..f12a841f --- /dev/null +++ b/Problem3.java @@ -0,0 +1,105 @@ +//We update the board in-place using state encoding so we don’t need an extra grid. +// +//Encoding: +//0 = dead → dead +//1 = alive → alive +//2 = alive → dead (was alive originally) +//3 = dead → alive (was dead originally) + +//Pass 1: mark transitions using these codes (while still being able to read original state) +//Pass 2: convert 2 → 0 and 3 → 1 +//To count live neighbors, treat cells as originally alive if value is 1 or 2. + +//Time: O(m × n) +//Space: O(1) extra + +class Solution { + + // 8 possible directions around a cell (neighbors) + int[][] dirs; + + // Board dimensions + int m, n; + + public void gameOfLife(int[][] board) { + + // All 8 neighbor directions (row delta, col delta) + this.dirs = new int[][]{ + {-1, -1}, {-1, 0}, {-1, 1}, + { 0, -1}, { 0, 1}, + { 1, -1}, { 1, 0}, { 1, 1} + }; + + // Store dimensions for boundary checks + this.m = board.length; + this.n = board[0].length; + + // PASS 1: Decide next state, but store it using encoded values + // We must preserve "original state" info while updating in-place. + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + + // Count number of alive neighbors around (i, j) + int count = getCount(board, i, j); + + // Rule: Dead cell with exactly 3 live neighbors becomes alive + if (board[i][j] == 0 && count == 3) { + board[i][j] = 3; // 0 -> 1 transition (dead -> alive) + } + + // Rule: Live cell dies if <2 or >3 live neighbors + else if (board[i][j] == 1 && (count < 2 || count > 3)) { + board[i][j] = 2; // 1 -> 0 transition (alive -> dead) + } + + // Otherwise: + // - dead stays dead + // - alive stays alive + // and we keep the cell as 0 or 1 as-is + } + } + + // PASS 2: Finalize the board by converting transitional states + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + + // If it was alive and should become dead + if (board[i][j] == 2) { + board[i][j] = 0; + } + + // If it was dead and should become alive + else if (board[i][j] == 3) { + board[i][j] = 1; + } + } + } + } + + // Count how many live neighbors exist around cell (i, j) + private int getCount(int[][] board, int i, int j) { + + int count = 0; + + // Check all 8 directions + for (int[] dir : dirs) { + + int r = i + dir[0]; + int c = j + dir[1]; + + // Boundary check to ensure neighbor is inside the board + if (r >= 0 && c >= 0 && r < m && c < n) { + + // IMPORTANT: + // 1 = originally alive and stays alive + // 2 = originally alive but will die + // Both should be counted as "alive" for neighbor counting + if (board[r][c] == 1 || board[r][c] == 2) { + count++; + } + } + } + + return count; + } +} \ No newline at end of file