Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions MergeSortedArray.swift
Original file line number Diff line number Diff line change
@@ -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
}
}

}
47 changes: 47 additions & 0 deletions RemoveDuplicatesFromSortedArray.swift
Original file line number Diff line number Diff line change
@@ -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..<nums.count {
if (nums[i] == nums[i - 1]) {
count += 1
} else {
count = 1
}

if (count <= 2) {
nums[slow] = nums[i]
slow += 1
}
}
return slow
}
}
66 changes: 66 additions & 0 deletions SearchIn2DMatrix2.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
//
// SearchInMatrix2.swift
// DSA-Practice
//
// Created by Paridhi Malviya on 1/12/26.
//

/*
Multiple approaches
BruteForce -> 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
}

}