From 6389126a23aa50007eb59c50fa8cc8db483184bb Mon Sep 17 00:00:00 2001 From: Paridhi Malviya Date: Mon, 12 Jan 2026 20:51:51 -0600 Subject: [PATCH] Two-Pointers-2 --- MergeSortedArray.swift | 73 +++++++++++++++++++++++++++ RemoveDuplicatesFromSortedArray.swift | 47 +++++++++++++++++ SearchIn2DMatrix2.swift | 66 ++++++++++++++++++++++++ 3 files changed, 186 insertions(+) create mode 100644 MergeSortedArray.swift create mode 100644 RemoveDuplicatesFromSortedArray.swift create mode 100644 SearchIn2DMatrix2.swift diff --git a/MergeSortedArray.swift b/MergeSortedArray.swift new file mode 100644 index 00000000..97d2dfe7 --- /dev/null +++ b/MergeSortedArray.swift @@ -0,0 +1,73 @@ +// +// MergeSortedArray.swift +// DSA-Practice +// +// Created by Paridhi Malviya on 1/8/26. +// + +//time complexity - O(m+n) +//no extra space +/* + [1, 6, 7, 0, 0, 0] + [2, 3, 5] + If we start the pointers from the start and use swapping technique then Swapping wouldn't work because order of elements might get disturbed in 2nd array. + + Approach 1 -> + We can create a new array to accomodate new sorted array. But extra space of O(m+n would be needed). + check array1[p1] <= array2[p2] { + add array[p1] in result array + increment p1 + } else { + add array[p2] in result array + increament p2 + } + + Approach 2 - without using extra O(m+n) space and using swapping technique. Use 3 pointers from the last. + there is no issue in overwritting in elements. + In order to solve sorting issue - use below approach + start pointer from the end + array1 -> start pointer from the end (pointer 1) + array2 -> start pointer from the end (pointer 2) + collecting pointer -> at the end of the first array where we are putting up values at the place of 0. + compare 7 and 5. array one's 7 is the bigger one. put 7 at the position of collecting pointer. Move array1 poniter towards left. + Move collecting pointer towards left. + We wouldn't be loosing sorting of the array because collecting pointer and the comparing pointers are at the different place. + time comlexity - O(m + n) + + two case -> when 2nd array finishes first. + when 1st array finishes first + */ + +class MergeSortedArray { + + init() { + var nums1 = [4,5,6,0,0,0] //[1, 6, 7, 0, 0, 0] + let nums2 = [1,2,3] //[2, 3, 5] + mergeSortedArray(nums1: &nums1, nums2: nums2, m: 3, n: 3) + print("nums1 after mergin sorted array \(nums1)") + } + + func mergeSortedArray(nums1: inout [Int], nums2: [Int], m: Int, n: Int) { + var collectingP: Int = m + n - 1 + var p2: Int = n - 1 + var p1 = m - 1 + + while (p1 >= 0 && p2 >= 0) { + if (nums1[p1] >= nums2[p2]) { + nums1[collectingP] = nums1[p1] + p1 -= 1 + } else { + nums1[collectingP] = nums2[p2] + p2 -= 1 + } + collectingP -= 1 + } + + while (p2 >= 0) { + nums1[collectingP] = nums2[p2] + p2 -= 1 + collectingP -= 1 + } + } + +} diff --git a/RemoveDuplicatesFromSortedArray.swift b/RemoveDuplicatesFromSortedArray.swift new file mode 100644 index 00000000..4e8400dd --- /dev/null +++ b/RemoveDuplicatesFromSortedArray.swift @@ -0,0 +1,47 @@ +// +// RemoveDuplicatesFromSortedArray.swift +// DSA-Practice +// +// Created by Paridhi Malviya on 1/12/26. +// + +/* + k = 1 means duplicates are not allowed + k = 2 means duplicates are allowed + k = 3 an element is allowed 3 times + + approach 1 -> have hash map. extra space - O(n). avoid extra space + approach 2- Perfectly O(n). No extra space + an element is visited twice. So, O(2n) = O(n) + + + */ +class RemoveDuplicatesFromSortedArray { + + + init() { + let indexOfLastElement = removeDuplicatesFromSortedArray(nums: [0,0,1,1,1,1,2,3,3]) + print("remove duplicates \(indexOfLastElement)") + } + + func removeDuplicatesFromSortedArray(nums: [Int]) -> Int { + var nums = nums + var slow = 1 + let i = 1 + var count = 1 + + for i in 1.. linear traversal in row and column - O(mn), no extra space + approach 1 - binary search on each row + m log n -> in each row, check the range, If the element lies in range 1 - 15 then do binary search. If not, then go to the next row. + n log m -> In each column, check the range and see if element can lie in that. Then do binary search on the column. If no of columns are smaller then this one is better. + m + n -> Using steps -> can start from top right element. In column from 0 to end, the numbers are increasing. In row, from end to 0, the numbers are decreasing + If I start from 0,0 and element is 6 then I can go towards row side and towards colmns side also, thats why we can choose top right corner and bottom left corner. Because we will have proper choices. + we calculate time complexity using worst case. m - 1 million, n also 1 million. always think array as 1 million * 1 million. + */ + +class SearchInTwoDMatrix { + + init() { + let isPresent = searchInTwoDMatrix(matrix: [[1,4,7,11,15], [2,5,8,12,19], [3,6,9,16,22], [10,13,14,17,24], [18,21, 23, 26, 30]], target: 14) + print("isPresent \(isPresent)") + } + + func searchInTwoDMatrix(matrix: [[Int]], target: Int) -> Bool { + let m = matrix.count + let n = matrix[0].count + + var i = 0 + var j = n - 1 + //from top right corner + while (i < m && j >= 0) { + //i++, j-- + if (matrix[i][j] == target) { + return true + } else if (matrix[i][j] > target) { + j -= 1 + } else { + i += 1 + } + } + return false + } + + func searchInTwoDMatrixFromBottomLeftCorner(matrix: [[Int]], target: Int) -> Bool { + let m = matrix.count + let n = matrix[0].count + + var i = m - 1 + var j = 0 + //from top right corner + while (j < n && i >= 0) { + //i++, j-- + if (matrix[i][j] == target) { + return true + } else if (matrix[i][j] > target) { + i -= 1 + } else { + j += 1 + } + } + return false + } + +}