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
Binary file added .DS_Store
Binary file not shown.
74 changes: 74 additions & 0 deletions ImplementSet.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
//
// S30Programs.swift
// DSA-Practice
//
// Created by Paridhi Malviya on 12/24/25.
//


//We are implementing Set with double hashing
class ImplementSet {

//primary storage
private var storage: [[Bool]?]
//length of primary array
private var buckets: Int
//length of nested array
private var bucketItems: Int

private func hash1(key: Int) -> Int {
//primary bucket
return key % buckets
}

private func hash2(key: Int) -> Int {
//nested array bucket
return key / bucketItems
}


init() {
buckets = 1000
bucketItems = 1000
storage = Array(repeating: nil, count: buckets)
}

//primary array contains the pointer to the nested array.
//secondary array contains the items which has the same hash1 value. To identify items uniquely in secondary array, apply hash2. After hash2, you will find an index, set that index's value to true.
//O(1)
func add(key: Int) {
let bucket = hash1(key: key)

if (storage[bucket] == nil) {
//there is no nested arrey, so create a nested array
if (bucket == 0) {
storage[bucket] = Array(repeating: false, count: bucketItems + 1)
} else {
storage[bucket] = Array(repeating: false, count: bucketItems)
}
}
let bucketItem = hash2(key: key)
storage[bucket]![bucketItem] = true
}

func remove(key: Int) {
//find out the primary array bucket
let bucket = hash1(key: key)
//if there is no nested array, just return. Wouldn't remove anything
if (storage[bucket] == nil) {
return
}
let bucketItem = hash2(key: key)
storage[bucket]![bucketItem] = false
}

func contains(key: Int) -> Bool {
let bucket = hash1(key: key)
let bucketItem = hash2(key: key)
//if there is no nested array, return false
if (storage[bucket] == nil) {
return false
}
return storage[bucket]![bucketItem]
}
}
159 changes: 159 additions & 0 deletions min stack/LinkedListToStackAdapter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
//
// LinkedListToStackAdapter.swift
// DSA-Practice
//
// Created by Paridhi Malviya on 12/16/25.
//

//Implement stack using linked list

class LLNode<T> {
var value: T
var next: LLNode<T>?

init(value: T, next: LLNode<T>?) {
self.value = value
self.next = next
}
}

class LLLinkedList<T> {
private var head: LLNode<T>?
private var tail: LLNode<T>?

var isEmpty: Bool {
return head == nil
}

var count: Int {
var currentHead = head
var count = 0
while (currentHead != nil) {
count += 1
currentHead = currentHead?.next
}
return count
}

init() {

}
}

extension LLLinkedList {
func append(value: T) {
let newNode = LLNode(value: value, next: nil)
if head == nil {
//means linkedlist is empty, so set the newnode as the head and tail both
tail = newNode
head = newNode
} else {
//if linked list is not empty then do normal appending
tail?.next = newNode
tail = newNode
}
}

func prepend(value: T) {
let newNode = LLNode(value: value, next: nil)
if head == nil {
//linked list is empty
head = LLNode(value: value, next: nil)
tail = head
} else {
// linked list is not empty
newNode.next = head
head = newNode
}
}

func removeFirstNode() -> LLNode<T>? {
if (head == nil) {
//it means the ll is empty
return nil
} else {
//if the ll is not empty
let currentHead = head
if let nextNode = head?.next {
head = nextNode
} else if (head?.next == nil) {
head = nil
}
return currentHead
}
}

var currentHead: LLNode<T>? {
return head
}
}

extension LLLinkedList: CustomStringConvertible {
var description: String {
var currentNode = head
var descString = "["
while currentNode != nil {
descString += "\(String(describing: currentNode?.value))"
currentNode = currentNode?.next
if (currentNode != nil) {
descString += ","
}
}
return descString + "]"
}
}

class StackUsingLL<T>: CustomStringConvertible {
private var llList: LLLinkedList<T>?

init(llList: LLLinkedList<T>) {
self.llList = llList
}

func push(value: T) {
//append the first element at the start of the linked list
llList?.prepend(value: value)
}

func pop() -> T? {
//remove the first node from the linked list and return it.
let removedItem = llList?.removeFirstNode()
return removedItem?.value
}

func peek() -> T? {
return llList?.currentHead?.value
}

func isEmpty() -> Bool {
return llList?.isEmpty ?? true
}

var description: String {
var currentHead = llList?.currentHead
var descString = "["
while (currentHead != nil) {
descString += "\(currentHead!.value)"
currentHead = currentHead!.next
if (currentHead != nil) {
descString += ","
}
}
return descString + "]"
}
}

class LinkedListToStackAdapter {

init() {
let stack = StackUsingLL<Int>(llList: LLLinkedList())
stack.push(value: 2)
stack.push(value: 3)
stack.push(value: 6)
let poppedElement = stack.pop()
print("popped element \(poppedElement, default: "NA")")
let topElement = stack.peek()
print("topElement \(topElement, default: "NA")")
print("printed linked list \(stack.description)")
}
}
77 changes: 77 additions & 0 deletions min stack/MinStack.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
//
// ImplementMinStack.swift
// DSA-Practice
//
// Created by Paridhi Malviya on 12/24/25.
//

//Min stack - supports push, pop, top and retrieving the minimum element in constant time.

class MinStack {

var stack: StackUsingLL<Int> = StackUsingLL<Int>(llList: LLLinkedList())

/*
Min stack maintains 1:1 mapping with the main element and the minimum element.
At the 4th push to the stack, min stack contains the minimum at the 4th index in all elements present at 0 to 4th index.
Either we cna maintain a min stack or can store a tuple in the main stack. Pair(current element, current minimum)
*/
var minStack: StackUsingLL<Int> = StackUsingLL<Int>(llList: LLLinkedList())

private var currentMin: Int

init() {
self.currentMin = Int.max
self.minStack.push(value: self.currentMin)
}


//it will pop the top element
func pop() -> Int? {
if (!stack.isEmpty()) {
let topElement = stack.pop()!
let _ = minStack.pop()
currentMin = minStack.peek()!
return topElement
}
return nil
}

//it will push the element
func push(val: Int) {
let minimum = min(currentMin, val)
stack.push(value: val)
minStack.push(value: minimum)
}

//it will return the top element
func top() -> Int? {
return stack.peek()
}

//it will return the min element in the stack
func getMin() -> Int {
return currentMin
//or can return minStack.peek()
}
}

class ImplementMinStack {

//Implement this stack using linked list because push and pop can happen in O(1) time cmplexity.
//Take 1 stack to keep min items.

init() {
let items: [Any] = [12, 8, 10, 1, 2, "P", "P", 3, "P", "P", "P"]

let minStack = MinStack()
for item in items {
if (item is Int) {
minStack.push(val: item as! Int)
} else {
let removedElement = minStack.pop()
print("removedElement \(String(describing: removedElement))")
}
}
}
}