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

/*
O(n)
O(n)
use hashset having the nodes especially the node address.
Most of the linked list problems can be optimized with the extra space.

Floyd's algorithm -
take a slow pointer and a fast pointer.
Move slow by 1x and fast by 2x
check if they have met or not.

If they didn't meet and fast goes out of the list. then it's not cyclic.
think about the even and odd lenght linekd list.
for even length -> fast != nil
for odd length -> fast.next != nil

In the first cycle -> the slow will be caught by fast one, no matter where slow and fast starts off. EVen if they are diagonally opposite, fast will be able to catch slow in the first cycle of slow.

For 3x -> we can't guarantee that they will meet in optimal manner.

How to figure out the head of the cycle ->
The distance of the head of the linked list is ->
O(2n), no extra space - O(1)
*/

class CyclicLinkedList {
init() {

}

func detectCycle(_ head: LLNode<Int>?) -> LLNode<Int>? {
if (head?.next == nil) {
return nil
}

var slow = head?.next
var fast = head?.next?.next
while(slow !== fast) {
if (fast?.next == nil || fast?.next?.next == nil) {
return nil
}
slow = slow?.next
fast = fast?.next?.next
}

//slow and fast are meeting, so there is a cycle. now, iterate from head and the slow pointer, where both pointers meet, that would be the beginning of the cycle
fast = head
while (fast !== slow) {
fast = fast?.next
slow = slow?.next
}
return slow
}


func detectingTheHeadOfTheCycle() {

}
}
50 changes: 50 additions & 0 deletions RemoveNthElementFromLast.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//
// RemoveElementFromLast.swift
// DSA-Practice
//
// Created by Paridhi Malviya on 1/15/26.
//

/*
Bruteforce - 2 pass algorithm -
first push all elements in the stack. Then don'r pick the element at the nth position and pick other eleent and form the linked list

approach2 - > 2 pass algorithm. move through the linked to count the no of elemtns.
no of elements - n-> pos
now, traverse until the counter is pos. Then remove the next node.

1 pass algorithm -
use slow pointer, fast pointer - move th window until fast == nil. When fast =nil, at that moment, slow is at the position one step before the node I need to remove. I can remove the node.
to remove the last element, maintain a dummy node at the start of the linked list.
to remove the first node, dummy node will be useful. dummy.next = head of the linked list.
*/

class RemoveNthNodeFromEnd {

init() {

}

func removeNthFromEnd(_ head: ListNode?, _ n: Int) -> ListNode? {
var count = 0
let dummy = ListNode(-1)
dummy.next = head
var slow: ListNode? = dummy
var fast: ListNode? = dummy
while (count <= n) {
fast = fast?.next
count += 1
}

while (fast != nil) {
fast = fast?.next
slow = slow?.next
}
let temp = slow?.next
slow?.next = slow?.next?.next
temp?.next = nil
return dummy.next

}

}
114 changes: 114 additions & 0 deletions ReverseLinkedList.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
//
// ReverseLinkedList.swift
// DSA-Practice
//
// Created by Paridhi Malviya on 1/15/26.
//

/*
reverse linked list -
approach 1 -> store all nodes in stack and start unfolding the stack.
use array. put elements in array and then traverse from the end.

In linked list problem, we can avoid using extra space.


using 3 pointers ->
current, previous, next

before you lose the connection with the node, store it in a temp variable.

Approach 3 -> recursion. O(n) space - for recursion stack
O(n) - time complexity

*/

public class ListNode {
public var val: Int
public var next: ListNode?
public init() { self.val = 0; self.next = nil; }
public init(_ val: Int) { self.val = val; self.next = nil; }
public init(_ val: Int, _ next: ListNode?) { self.val = val; self.next = next; }
}

class ReverseLinkedList {

func reverseList(_ head: LLNode<Int>?) -> LLNode<Int>? {
if (head == nil || head?.next == nil) {
return head
}

var current = head //ListNode?
var prev: LLNode<Int>? //ListNode?
var temp: LLNode<Int>?
while(current != nil) {
temp = current?.next
current?.next = prev
prev = current
current = temp
}
return prev
}

var result: LLNode<Int>?
func reverseListByRecursionUsingPointers(_ head: LLNode<Int>?) -> LLNode<Int>? {
var prev: LLNode<Int>?
reverse(head, prev: prev)
return result
}

func reverse(_ current: LLNode<Int>?, prev: LLNode<Int>?) {
var prev = prev
var current = current
if (current == nil) {
result = prev
return
}

let temp = current?.next
current?.next = prev
prev = current
current = temp

reverse(current, prev: prev)
}

//MARK: using in built recursion stack

var newHead: LLNode<Int>?
func reverseUsingRecursionStack(_ head: LLNode<Int>?) -> LLNode<Int>? {
reverseRecursionStack(head)
return result
}

func reverseRecursionStack(_ head: LLNode<Int>?) {
if (head == nil || head?.next == nil) {
newHead = head
return
}
reverseRecursionStack(head?.next)
head?.next?.next = head
head?.next = nil
return
}

//MARK: using in built stack, using Node return type
func reverseListUsingNodeReturnType(_ head: ListNode?) -> ListNode? {
return reverseUsingNodeReturnType(head)
}

//O(n) - time complexity, O(n)- recursion stack
func reverseUsingNodeReturnType(_ head: ListNode?) -> ListNode? {
if (head == nil || head?.next == nil) {
return head
}
//result is not parameter of recursion, so it will remain constant. If stack unfolds, the head will change, but result will remain constant.
let result = reverseUsingNodeReturnType(head?.next)
head?.next?.next = head
head?.next = nil
return result
}


}