Skip to content

Commit cbd80d7

Browse files
committed
Add Linked List
* Flatten Multi Level List * Remove Kth Last Node * Linked List Reversal * Linked List Intersection * Palindromic Linked List * LRU Cache
1 parent 77cb109 commit cbd80d7

File tree

7 files changed

+249
-0
lines changed

7 files changed

+249
-0
lines changed
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import ds.MultiLevelListNode
2+
3+
/*
4+
Definition for a MultiLevelListNode:
5+
data class MultiLevelListNode(
6+
var value: Int,
7+
var next: MultiLevelListNode? = null,
8+
var child: MultiLevelListNode? = null
9+
)
10+
*/
11+
12+
fun flattenMultiLevelList(head: MultiLevelListNode?): MultiLevelListNode? {
13+
if (head == null) {
14+
return null
15+
}
16+
var tail = head
17+
// Find the tail of the linked list at the first level.
18+
while (tail?.next != null) {
19+
tail = tail.next
20+
}
21+
var curr = head
22+
// Process each node at the current level. If a node has a child linked list,
23+
// append it to the tail and then update the tail to the end of the extended
24+
// linked list. Continue until all nodes at the current level are processed.
25+
while (curr != null) {
26+
if (curr.child != null) {
27+
tail?.next = curr.child
28+
// Disconnect the child linked list from the current node.
29+
curr.child = null
30+
while (tail?.next != null) {
31+
tail = tail.next
32+
}
33+
}
34+
curr = curr.next
35+
}
36+
return head
37+
}

kotlin/Linked Lists/LRUCache.kt

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
data class DoublyLinkedListNode(val key: Int, val value: Int) {
2+
var next: DoublyLinkedListNode? = null
3+
var prev: DoublyLinkedListNode? = null
4+
}
5+
6+
class LRUCache {
7+
8+
private val capacity: Int
9+
private val hashmap: MutableMap<Int, DoublyLinkedListNode>
10+
private val head: DoublyLinkedListNode
11+
private val tail: DoublyLinkedListNode
12+
13+
constructor(capacity: Int) {
14+
this.capacity = capacity
15+
// A hash map that maps keys to nodes.
16+
this.hashmap = mutableMapOf()
17+
// Initialize the head and tail dummy nodes and connect them to
18+
// each other to establish a basic two-node doubly linked list.
19+
this.head = DoublyLinkedListNode(-1, -1)
20+
this.tail = DoublyLinkedListNode(-1, -1)
21+
this.head.next = this.tail
22+
this.tail.prev = this.head
23+
}
24+
25+
fun get(key: Int): Int {
26+
if (key !in hashmap) {
27+
return -1
28+
}
29+
// To make this key the most recently used, remove its node and
30+
// re-add it to the tail of the linked list.
31+
val node = hashmap[key]!!
32+
removeNode(node)
33+
addNodeToTail(node)
34+
return node.value
35+
}
36+
37+
fun put(key: Int, value: Int) {
38+
// If a node with this key already exists, remove it from the
39+
// linked list.
40+
if (key in hashmap) {
41+
removeNode(hashmap[key]!!)
42+
}
43+
val node = DoublyLinkedListNode(key, value)
44+
hashmap[key] = node
45+
// Remove the least recently used node from the cache if adding
46+
// this new node will result in an overflow.
47+
if (hashmap.size > capacity) {
48+
hashmap.remove(head.next!!.key)
49+
removeNode(head.next!!)
50+
}
51+
addNodeToTail(node)
52+
}
53+
54+
private fun addNodeToTail(node: DoublyLinkedListNode) {
55+
val prevNode = tail.prev
56+
node.prev = prevNode
57+
node.next = tail
58+
prevNode!!.next = node
59+
tail.prev = node
60+
}
61+
62+
private fun removeNode(node: DoublyLinkedListNode) {
63+
node.prev!!.next = node.next
64+
node.next!!.prev = node.prev
65+
}
66+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import ds.ListNode
2+
3+
/*
4+
Definition of ListNode:
5+
data class ListNode(var value: Int = 0, var next: ListNode? = null)
6+
*/
7+
8+
fun linkedListIntersection(headA: ListNode?, headB: ListNode?): ListNode? {
9+
var ptrA = headA
10+
var ptrB = headB
11+
// Traverse through list A with 'ptrA' and list B with 'ptrB'
12+
// until they meet.
13+
while (ptrA != ptrB) {
14+
// Traverse list A -> list B by first traversing 'ptrA' and
15+
// then, upon reaching the end of list A, continue the
16+
// traversal from the head of list B.
17+
ptrA = if (ptrA != null) ptrA.next else headB
18+
// Simultaneously, traverse list B -> list A.
19+
ptrB = if (ptrB != null) ptrB.next else headA
20+
}
21+
// At this point, 'ptrA' and 'ptrB' either point to the
22+
// intersection node or both are null if the lists do not
23+
// intersect. Return either pointer.
24+
return ptrA
25+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import ds.ListNode
2+
3+
/*
4+
Definition of ListNode:
5+
data class ListNode(var value: Int = 0, var next: ListNode? = null)
6+
*/
7+
8+
fun linkedListReversal(head: ListNode?): ListNode? {
9+
var currNode = head
10+
var prevNode: ListNode? = null
11+
// Reverse the direction of each node's pointer until 'currNode'
12+
// is null.
13+
while (currNode != null) {
14+
val nextNode = currNode.next
15+
currNode.next = prevNode
16+
prevNode = currNode
17+
currNode = nextNode
18+
}
19+
// 'prevNode' will be pointing at the head of the reversed linked
20+
// list.
21+
return prevNode
22+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import ds.ListNode
2+
3+
/*
4+
Definition of ListNode:
5+
data class ListNode(var value: Int = 0, var next: ListNode? = null)
6+
*/
7+
8+
fun linkedListReversalRecursive(head: ListNode?): ListNode? {
9+
// Base cases.
10+
if (head == null || head.next == null) {
11+
return head
12+
}
13+
// Recursively reverse the sublist starting from the next node.
14+
val newHead = linkedListReversalRecursive(head.next)
15+
// Connect the reversed linked list to the head node to fully
16+
// reverse the entire linked list.
17+
head.next!!.next = head
18+
head.next = null
19+
return newHead
20+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import ds.ListNode
2+
3+
/*
4+
Definition of ListNode:
5+
data class ListNode(var value: Int = 0, var next: ListNode? = null)
6+
*/
7+
8+
fun palindromicLinkedList(head: ListNode?): Boolean {
9+
// Find the middle of the linked list and then reverse the second half of the
10+
// linked list starting at this midpoint.
11+
val mid = findMiddle(head)
12+
val secondHead = reverseList(mid)
13+
// Compare the first half and the reversed second half of the list
14+
var ptr1 = head
15+
var ptr2 = secondHead
16+
var res = true
17+
while (ptr2 != null) {
18+
if (ptr1?.value != ptr2?.value) {
19+
res = false
20+
}
21+
ptr1 = ptr1?.next
22+
ptr2 = ptr2?.next
23+
}
24+
return res
25+
}
26+
27+
// From the 'Reverse Linked List' problem.
28+
fun reverseList(head: ListNode?): ListNode? {
29+
var prev: ListNode? = null
30+
var curr = head
31+
while (curr != null) {
32+
val next = curr.next
33+
curr.next = prev
34+
prev = curr
35+
curr = next
36+
}
37+
return prev
38+
}
39+
40+
// From the 'Linked List Midpoint' problem.
41+
fun findMiddle(head: ListNode?): ListNode? {
42+
var slow = head
43+
var fast = head
44+
while (fast != null && fast.next != null) {
45+
slow = slow?.next
46+
fast = fast.next?.next
47+
}
48+
return slow
49+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import ds.ListNode
2+
3+
/*
4+
Definition of ListNode:
5+
data class ListNode(var value: Int = 0, var next: ListNode? = null)
6+
*/
7+
8+
fun removeKthLastNode(head: ListNode?, k: Int): ListNode? {
9+
// A dummy node to ensure there's a node before 'head' in case we
10+
// need to remove the head node.
11+
val dummy = ListNode(-1)
12+
dummy.next = head
13+
var trailer = dummy
14+
var leader = dummy
15+
// Advance 'leader' k steps ahead.
16+
repeat(k) {
17+
// If k is larger than the length of the linked list, no node
18+
// needs to be removed.
19+
leader = leader.next ?: return head
20+
}
21+
// Move 'leader' to the end of the linked list, keeping 'trailer'
22+
// k nodes behind.
23+
while (leader.next != null) {
24+
leader = leader.next!!
25+
trailer = trailer.next!!
26+
}
27+
// Remove the kth node from the end.
28+
trailer.next = trailer.next?.next
29+
return dummy.next
30+
}

0 commit comments

Comments
 (0)