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
78 changes: 78 additions & 0 deletions ContainerWithMostWater.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
//
// TrapRainWater.swift
// DSA-Practice
//
// Created by Paridhi Malviya on 1/7/26.
//

/*
heights array = [1, 8, 6, 2, 5, 4, 8, 3, 7]
Area = h * w
naive - nested iterations from each elemnt. keep the global value for maximum area. O(n2) Need to remove these.
effective height - lesser height. because we have to consider the lesser height. whch can contain water.
go away from smalller height.
width will decrease when we move pointers.

time complexity - O(n)
when left adn right pointers meet, stop the

Tactic - nested iterations are getting eliminated if we check 1 and 7 only. nested iterations from 1 can be eliminated. because the area will be squizzed if we move right pointer. 1 was constraining height.
we explored maximum area from 1. we can confidently move our left pointer

2nd aread = 7 * 7 = 49. left pointer height = 8. right pointer height - 7. so effective height - 7
width = right pointer index - left pointer index.
height - effective height

2 pointer - move either left or right or both.

O(n)
*/
class ContainerWithMaxArea {

init() {
let area = maxAreaBruteOptimized(heights: [1, 8, 6, 2, 5, 4, 8, 3, 7])
print("area \(area)")
}

func maxAreaBruteforce(heights: [Int]) {
let n = heights.count
var maximum = 0
for i in 0..<n {
for j in (i + 1)..<n {
let currentArea = min(heights[i], heights[j]) * (j - i)
maximum = max(maximum, currentArea)
}
}
}

func maxAreaBruteOptimized(heights: [Int]) -> Int {
let n = heights.count
var maximum = 0
var left = 0
var right = n - 1

//This is to find the indices which contains the maximum area
var start = 0
var end = 0

//heights[left] == heights[right], we can move either left or right pointer. Both will work
while (left < right) {
let currentArea = min(heights[left], heights[right]) * (right - left)

if (maximum < currentArea) {
maximum = currentArea
start = left
end = right
}

maximum = max(maximum, currentArea)
if (heights[left] <= heights[right]) {
left += 1
} else {
right -= 1
}
}
print("start \(start) *** end \(end)")
return maximum
}
}
66 changes: 66 additions & 0 deletions SortColors.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
//
// ArrangeColors.swift
// DSA-Practice
//
// Created by Paridhi Malviya on 1/7/26.
//

/*
using 3 pointers - we can sort it in a single pass.
We can't go ahead for furhter pointers. We can extrapolate to have 100 pointers....
All sortnig algorithm could be O(n) then.
But we need to use sorting algorithm for this kind of requirement. which is O(n log n)

//segregate 0, 1, and 2
have 2 pointers.
lef tis collecting all 0s,
right is collecting all 2s
mid will be itertaitn gthrough the array
if (nums[mid] == nums[right]) {
swap element at mid with the one at right
right -= 1
} else if (nums[mid] == 0) {
swap mid element with left element
left += 1, mid += 1
} else if (nums[mid == 1]){
mid += 1
}

mid and right has crossed each other so stop.
while (mid <= right ) {
}

O(n) -> single pass algorithm for sorting colors
*/

class SortColors {

init() {
var array = [2, 0, 2, 1, 1, 0]
// var array = [1, 2, 0]
let sortedNums = sortColors(&array)
print("array \(sortedNums)")
}

func sortColors(_ nums: inout [Int]) -> [Int] {
var nums = nums
let n = nums.count
var left = 0
var right = n - 1
var mid = 0

while (mid <= right) {
if (nums[mid] == 2) {
nums.swapAt(mid, right)
right -= 1
} else if (nums[mid] == 0) {
nums.swapAt(mid, left)
left += 1
mid += 1
} else {
mid += 1
}
}
return nums
}
}
118 changes: 118 additions & 0 deletions ThreeSum.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
//
// ThreeSum.swift
// DSA-Practice
//
// Created by Paridhi Malviya on 1/11/26.
//

/*
find triplet sum of which can give a particular target.
avoid duplicate triplet.
By sorting the triplet numbers

bruteforce - native - have nested triple iterations. n3. O(n) space for hash set.
fix 1 pointer. On rest of the array, do 2 sum. 2 sum can be implmented using 2-pointer.

optimized Approach 1 -> using hash set
time complexity - O(n2) space -> O(n)

hashing of string -> aba -> prime for each character character

Optimized approach 2 -> sort the array. Fix a pointer i at 1 element i.e. k. have left pointer and right pointer. check for 2 sum for (target - k) sum
move to next unique element.
When left pointer crosses right pointer, we will be done.
Keep on moving the pointer i (remove external duplicacy) - move until we get a next unique element
Stop when we get the value as 1. We can stop. We can never get sum =0
O(n2) + O (n log n)
space - O(1)

Binary search solution - O(n2 logn n) -
*/

class ThreeSum {

init() {
let resultArray = threeSum(nums: [-1, 0, 1, 2, -1, -4])
print("result : \(resultArray)")

let resultArrayUsingHashing = threeSumUsingHashing(nums: [-1, 0, 1, 2, -1, -4], target: 0)
print("resultArrayUsingHashing \(resultArrayUsingHashing)")
}

func threeSum(nums: [Int]) -> [[Int]] {
if (nums.count < 3) {
return [[]]
}
let n = nums.count
var result = [[Int]]()

let sortedNums = nums.sorted(by:<) //-4, -1, -1, 0, 1, 2

for i in 0..<n {
if (sortedNums[i] > 0) {
break
}
//to avoid external duplicacy
if (i > 0 && sortedNums[i] == sortedNums[i - 1]) {
continue
}
var left = i + 1
var right = n - 1
//left and right should not cross each other.
while (left < right) {
let sum = sortedNums[i] + sortedNums[left] + sortedNums[right]

if (sum == 0) {
//get the triplet
let triplet: [Int] = [sortedNums[i], sortedNums[left], sortedNums[right]]
result.append(triplet)
left += 1
right -= 1
//we don't want to repeat the duplicacy
//If we are mutating the base values then check the base case values again.
while (left < right && sortedNums[left] == sortedNums[left - 1]) {
left += 1
}

while (left < right && sortedNums[right] == sortedNums[right + 1]) {
right -= 1
}
} else if (sum < 0) {
left += 1
} else {
//sum > 0
right -= 1
}
}
}
return result
}

func twoSum(sortedNums: [Int], i: Int, results: inout [[Int]]) {
var seen = Set<Int>()
for j in (i + 1)..<sortedNums.count {
let complement = -sortedNums[i] - sortedNums[j]
if seen.contains(complement) {
results.append([sortedNums[i], sortedNums[j], complement])
// Optionally, skip duplicates of nums[j]
// while (j + 1 < sortedNums.count && sortedNums[j] == sortedNums[j + 1]) {
// continue
// }
}
// Record current number for future complements
seen.insert(sortedNums[j])
}
}

func threeSumUsingHashing(nums: [Int], target: Int) -> [[Int]] {
let sortedNums = nums.sorted()
var results = [[Int]]()
for i in 0..<sortedNums.count {
if (i == 0 || sortedNums[i - 1] != sortedNums[i]) {
twoSum(sortedNums: sortedNums, i: i, results: &results)
}
}
return results
}
}