From 7cd9b8269ceb3c3bd4ef960feb394ff9fecca7e4 Mon Sep 17 00:00:00 2001 From: Paridhi Malviya Date: Thu, 15 Jan 2026 11:52:41 -0600 Subject: [PATCH] Two pointers 1 --- ContainerWithMostWater.swift | 78 +++++++++++++++++++++++ SortColors.swift | 66 ++++++++++++++++++++ ThreeSum.swift | 118 +++++++++++++++++++++++++++++++++++ 3 files changed, 262 insertions(+) create mode 100644 ContainerWithMostWater.swift create mode 100644 SortColors.swift create mode 100644 ThreeSum.swift diff --git a/ContainerWithMostWater.swift b/ContainerWithMostWater.swift new file mode 100644 index 00000000..c4411fef --- /dev/null +++ b/ContainerWithMostWater.swift @@ -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.. 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 + } +} diff --git a/SortColors.swift b/SortColors.swift new file mode 100644 index 00000000..7dbdeaa3 --- /dev/null +++ b/SortColors.swift @@ -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 + } +} diff --git a/ThreeSum.swift b/ThreeSum.swift new file mode 100644 index 00000000..7cee650b --- /dev/null +++ b/ThreeSum.swift @@ -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.. 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() + for j in (i + 1).. [[Int]] { + let sortedNums = nums.sorted() + var results = [[Int]]() + for i in 0..