Skip to content

TypeScript: Chapter 3 Linked Lists #59

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
9bfe0d9
ts-3: linked list reversal
aikhelis Jan 31, 2025
8a59277
ts-3: camelCase naming
aikhelis Feb 1, 2025
0bbb177
ts-3: remove kth last node
aikhelis Feb 1, 2025
22ca124
ts-3: commend node definition
aikhelis Feb 1, 2025
2401f25
ts-3: intersection
aikhelis Feb 1, 2025
e08e1a1
ts-3: palindromic
aikhelis Feb 1, 2025
ac5cdd7
add: InvertBinaryTreeRecursive and InvertBinaryTreeIterative
Jer3myYu Feb 1, 2025
87309e4
add: BalancedBinaryTreeValidation
Jer3myYu Feb 1, 2025
cbf04e1
add: RightmostNodesOfABinaryTree
Jer3myYu Feb 1, 2025
20c0102
add: WidestBinaryTreeLevel
Jer3myYu Feb 1, 2025
92d90ef
add: BinarySearchTreeValidation, use null to replace float('-inf') an…
Jer3myYu Feb 1, 2025
13e7aef
add: LowestCommonAncestor
Jer3myYu Feb 1, 2025
54a8a98
add: BuildBinaryTree
Jer3myYu Feb 1, 2025
c92cbf9
add: MaximumPathSum
Jer3myYu Feb 1, 2025
8ae766c
add: BinaryTreeSymmetry
Jer3myYu Feb 1, 2025
e2a2499
add: BinaryTreeColumns
Jer3myYu Feb 1, 2025
a289665
add: KthSmallestNumberInBSTRecursive
Jer3myYu Feb 1, 2025
0c05a1e
add: KthSmallestNumberInBSTIterative
Jer3myYu Feb 1, 2025
5ba42ca
add: SerializeAndDeserializeABinaryTree
Jer3myYu Feb 1, 2025
dc941b6
ts-1 ts-2: naming aligned with language standard
aikhelis Feb 1, 2025
539d2ed
ts-3: flatten list
aikhelis Feb 2, 2025
e6a13e9
ts-3: align remove-kth-last-node with canonical solution with assumed…
aikhelis Feb 2, 2025
b6281d8
ts-3: added non-null assertions to inform typescript checks
aikhelis Feb 2, 2025
315a5f2
ts-3: lru cavhe
aikhelis Feb 2, 2025
a0b2254
ts-1: address typescript warning
aikhelis Feb 2, 2025
e7072d0
Merge branch 'main' into typescript_solutions_linked_lists
aikhelis Feb 2, 2025
acea417
ts-3: addressed review comments (imports, naming, ditch extra types)
aikhelis Feb 3, 2025
1af9cdd
ts-3: double linked list node defined in the same file
aikhelis Feb 4, 2025
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
38 changes: 38 additions & 0 deletions typescript/Linked Lists/flatten_multi_level_list.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { MultiLevelListNode } from "./ds";

/* Definition of MultiLevelListNode:
class MultiLevelListNode {
val: number;
next: MultiLevelListNode | null;
child: MultiLevelListNode | null;
constructor(val: number){
this.val = val;
this.next = null;
this.child = null;
}
}*/


function flattenMultiLevelList(head: MultiLevelListNode | null): MultiLevelListNode | null {
if (!head)
return head;
let tail: MultiLevelListNode | null = head;
// Find the tail of the linked list at the first level.
while (tail.next !== null)
tail = tail.next;
let curr: MultiLevelListNode | null = head;
// Process each node at the current level. If a node has a child linked list,
// append it to the tail and then update the tail to the end of the extended
// linked list. Continue until all nodes at the current level are processed.
while (curr !== null){
if (curr.child !== null){
tail.next = curr.child;
// Disconnect the child linked list from the current node.
curr.child = null;
while (tail.next !== null)
tail = tail.next;
}
curr = curr.next;
}
return head;
}
29 changes: 29 additions & 0 deletions typescript/Linked Lists/linked_list_intersection.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { ListNode } from './ds';

/* Definition of ListNode:
class ListNode {
val: number; next: ListNode | null;
constructor(val: number){
this.val = val;
this.next = null;
}
}*/


function linkedListIntersection(headA: ListNode | null, headB: ListNode | null): ListNode | null {
let ptrA = headA, ptrB = headB;
// Traverse through list A with 'ptrA' and list B with 'ptrB'
// until they meet.
while (ptrA !== ptrB) {
// Traverse list A -> list B by first traversing 'ptrA' and
// then, upon reaching the end of list A, continue the
// traversal from the head of list B.
ptrA = ptrA !== null ? ptrA.next : headB;
// Simultaneously, traverse list B -> list A.
ptrB = ptrB !== null ? ptrB.next : headA;
}
// At this point, 'ptrA' and 'ptrB' either point to the
// intersection node or both are null if the lists do not
// intersect. Return either pointer.
return ptrA;
}
27 changes: 27 additions & 0 deletions typescript/Linked Lists/linked_list_reversal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { ListNode } from './ds';

/* Definition of ListNode:
class ListNode {
val: number; next: ListNode | null;
constructor(val: number){
this.val = val;
this.next = null;
}
}*/

function linkedListReversal(head: ListNode | null): ListNode | null {
let currNode: ListNode | null = head;
let prevNode: ListNode | null = null;
// Reverse the direction of each node's pointer until 'currNode'
// is null.
while (currNode !== null){
const nextNode: ListNode | null = currNode.next;
currNode.next = prevNode;
prevNode = currNode;
currNode = nextNode;
}
// 'prevNode' will be pointing at the head of the reversed linked
// list.
return prevNode;
}

23 changes: 23 additions & 0 deletions typescript/Linked Lists/linked_list_reversal_recursive.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { ListNode } from './ds';

/* Definition of ListNode:
class ListNode {
val: number; next: ListNode | null;
constructor(val: number){
this.val = val;
this.next = null;
}
}*/

function linkedListReversalRecursive(head: ListNode | null): ListNode | null {
// Base cases.
if (!head || !head.next)
return head;
// Recursively reverse the sublist starting from the next node.
const newHead: ListNode | null = linkedListReversalRecursive(head.next);
// Connect the reversed linked list to the head node to fully
// reverse the entire linked list.
head.next.next = head;
head.next = null;
return newHead;
}
73 changes: 73 additions & 0 deletions typescript/Linked Lists/lru_cache.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { DoublyLinkedListNode } from './ds';

/* Definition of DoublyLinkedListNode:
class DoublyLinkedListNode {
key: number; val: number;
prev: DoublyLinkedListNode | null;
next: DoublyLinkedListNode | null;

constructor(key: number, val: number) {
this.key = key;
this.val = val;
this.prev = null;
this.next = null;
}
}*/

class LRUCache {
capacity: number;
hashmap: Map<number, DoublyLinkedListNode>;
head: DoublyLinkedListNode; tail: DoublyLinkedListNode;

constructor(capacity: number) {
this.capacity = capacity;
// A hash map that maps keys to nodes.
this.hashmap = new Map();
// Initialize the head and tail dummy nodes and connect them to
// each other to establish a basic two-node doubly linked list.
this.head = new DoublyLinkedListNode(-1, -1);
this.tail = new DoublyLinkedListNode(-1, -1);
this.head.next = this.tail;
this.tail.prev = this.head;
}

get(key: number): number {
if (!this.hashmap.has(key))
return -1;
// To make this key the most recently used, remove its node and
// re-add it to the tail of the linked list.
const node = this.hashmap.get(key)!;
this.removeNode(node);
this.addToTail(node);
return node.val;
}

put(key: number, val: number): void {
// If a node with this key already exists, remove it from the
// linked list.
if (this.hashmap.has(key))
this.removeNode(this.hashmap.get(key)!);
const node = new DoublyLinkedListNode(key, val);
this.hashmap.set(key, node);
// Remove the least recently used node from the cache if adding
// this new node will result in an overflow.
if (this.hashmap.size > this.capacity) {
this.hashmap.delete(this.head.next!.key);
this.removeNode(this.head.next!);
}
this.addToTail(node);
}

addToTail(node: DoublyLinkedListNode): void {
const prevNode = this.tail.prev;
node.prev = prevNode;
node.next = this.tail;
prevNode!.next = node;
this.tail.prev = node;
}

removeNode(node: DoublyLinkedListNode): void {
node.prev!.next = node.next;
node.next!.prev = node.prev;
}
}
51 changes: 51 additions & 0 deletions typescript/Linked Lists/palindromic_linked_list.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { ListNode } from './ds';

/* Definition of ListNode:
class ListNode {
val: number; next: ListNode | null;
constructor(val: number){
this.val = val;
this.next = null;
}
}*/

function palindromicLinkedList(head: ListNode | null): boolean {
// Find the middle of the linked list and then reverse the second half of the
// linked list starting at this midpoint.
const mid = findMiddle(head);
const secondHead = reverseList(mid);
// Compare the first half and the reversed second half of the list
let ptr1 = head, ptr2 = secondHead;
let res = true;
while (ptr2) {
if (ptr1!.val !== ptr2.val) {
res = false;
}
ptr1 = ptr1!.next, ptr2 = ptr2.next;
}
return res;
}

// From the 'Reverse Linked List' problem.
function reverseList(head: ListNode | null): ListNode | null {
let prevNode: ListNode | null = null;
let currNode: ListNode | null = head;
while (currNode) {
const nextNode = currNode.next;
currNode.next = prevNode;
prevNode = currNode;
currNode = nextNode;
}
return prevNode;
}

// From the 'Linked List Midpoint' problem.
function findMiddle(head: ListNode | null): ListNode | null {
let slow: ListNode | null = head;
let fast: ListNode | null = head;
while (fast && fast.next) {
slow = slow!.next;
fast = fast.next!.next;
}
return slow;
}
36 changes: 36 additions & 0 deletions typescript/Linked Lists/remove_kth_last_node.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { ListNode } from './ds';

/* Definition of ListNode:
class ListNode {
val: number; next: ListNode | null;
constructor(val: number){
this.val = val;
this.next = null;
}
}*/

function removeKthLastNode(head: ListNode | null, k: number): ListNode | null {
// A dummy node to ensure there's a node before 'head' in case we
// need to remove the head node.
let dummy: ListNode | null = new ListNode(-1);
dummy.next = head;
let trailer: ListNode | null = dummy;
let leader: ListNode | null = dummy;
// Advance 'leader' k steps ahead.
for (let i = 0; i < k; i++){
leader = leader.next;
// If k is larger than the length of the linked list, no node
// needs to be removed.
if (leader === null)
return head;
}
// Move 'leader' to the end of the linked list, keeping 'trailer'
// k nodes behind.
while (leader.next !== null){
leader = leader.next;
trailer = trailer!.next;
}
// Remove the kth node from the end.
trailer!.next = trailer!.next!.next;
return dummy.next;
}
2 changes: 1 addition & 1 deletion typescript/Two Pointers/triplet_sum_brute_force.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ function tripletSumBruteForce(nums: number[]): number[][] {
}
}
// [javascript] convert the Set back into an array of triplets.
return Array.from(triplets).map(JSON.parse);
return Array.from(triplets).map((str) => JSON.parse(str));
}