diff --git a/README.md b/README.md index c597e59..3d8c2c1 100644 --- a/README.md +++ b/README.md @@ -109,6 +109,7 @@ - [Task #33](src/neetcode/binary-search/median-of-two-sorted-arrays) – _Median Of Two Sorted Arrays_ - _[check the task](https://neetcode.io/problems/median-of-two-sorted-arrays)_ - Linked List - [Task #34](src/neetcode/linked-list/reversed-linked-list) – _Reversed Linked List_ - _[check the task](https://neetcode.io/problems/reverse-a-linked-list)_ + - [Task #35](src/neetcode/linked-list/merge-two-sorted-lists) – _Merge Two Sorted Lists_ - _[check the task](https://neetcode.io/problems/merge-two-sorted-linked-lists)_ [BigFrontEnd - JavaScript Coding Questions](https://bigfrontend.dev/problem) - [1. implement curry()](src/bigfrontend/javascript/curry) - _Curry Function_ - [check the task](https://bigfrontend.dev/problem/implement-curry) diff --git a/src/neetcode/linked-list/common.ts b/src/neetcode/linked-list/common.ts new file mode 100644 index 0000000..98741d1 --- /dev/null +++ b/src/neetcode/linked-list/common.ts @@ -0,0 +1,32 @@ +export class ListNode { + val: number; + next: ListNode | null; + constructor(val = 0, next = null) { + this.val = val; + this.next = next; + } +} + +export const createList = (values: number[]): ListNode | null => { + const dummy = new ListNode(); + let tail = dummy; + + for (const value of values) { + tail.next = new ListNode(value); + tail = tail.next; + } + + return dummy.next; +}; + +export const listToArray = (head: ListNode | null): number[] => { + const values: number[] = []; + let current = head; + + while (current) { + values.push(current.val); + current = current.next; + } + + return values; +}; diff --git a/src/neetcode/linked-list/merge-two-sorted-lists/solution.test.ts b/src/neetcode/linked-list/merge-two-sorted-lists/solution.test.ts new file mode 100644 index 0000000..9cfb342 --- /dev/null +++ b/src/neetcode/linked-list/merge-two-sorted-lists/solution.test.ts @@ -0,0 +1,47 @@ +import { createList, ListNode, listToArray } from '../common'; +import { mergeTwoLists } from './solution'; + +describe('Merge Two Sorted Lists | NeetCode | RoadMap | Testcases', () => { + test('merges two sorted linked lists', () => { + const list1 = createList([1, 2, 4]); + const list2 = createList([1, 3, 5]); + + expect(listToArray(mergeTwoLists(list1, list2))).toEqual([ + 1, 1, 2, 3, 4, 5, + ]); + }); + + test('returns null when both lists are empty', () => { + expect(mergeTwoLists(null, null)).toBeNull(); + }); + + test.each([ + ['first', null, createList([1, 2, 3])], + ['second', createList([1, 2, 3]), null], + ])( + 'returns the non-empty list when the %s list is empty', + (_, list1, list2) => { + const nonEmptyList = list1 ?? list2; + + expect(mergeTwoLists(list1, list2)).toBe(nonEmptyList); + }, + ); + + test('reuses the nodes from the original lists', () => { + const first = new ListNode(1); + const fourth = new ListNode(4); + first.next = fourth; + + const second = new ListNode(2); + const third = new ListNode(3); + second.next = third; + + const merged = mergeTwoLists(first, second); + + expect(merged).toBe(first); + expect(first.next).toBe(second); + expect(second.next).toBe(third); + expect(third.next).toBe(fourth); + expect(fourth.next).toBeNull(); + }); +}); diff --git a/src/neetcode/linked-list/merge-two-sorted-lists/solution.ts b/src/neetcode/linked-list/merge-two-sorted-lists/solution.ts new file mode 100644 index 0000000..70dcf0b --- /dev/null +++ b/src/neetcode/linked-list/merge-two-sorted-lists/solution.ts @@ -0,0 +1,33 @@ +import { ListNode } from '../common'; + +/** + * @param {ListNode} list1 - sorted linked list + * @param {ListNode} list2 - sorted linked list + * @return {ListNode} - the head of the new **sorted** linked list. + * The list should be made up of nodes from `list1` and `list2`. + */ +export const mergeTwoLists = ( + list1: ListNode | null, + list2: ListNode | null, +): ListNode | null => { + const dummy = new ListNode(); + let curr = dummy; + while (list1 !== null && list2 !== null) { + if (list1.val < list2.val) { + curr.next = list1; + list1 = list1.next; + } else { + curr.next = list2; + list2 = list2.next; + } + curr = curr.next; + } + + if (list1) { + curr.next = list1; + } else if (list2) { + curr.next = list2; + } + + return dummy.next; +}; diff --git a/src/neetcode/linked-list/reversed-linked-list/solution.test.ts b/src/neetcode/linked-list/reversed-linked-list/solution.test.ts index 204a2f5..0231f68 100644 --- a/src/neetcode/linked-list/reversed-linked-list/solution.test.ts +++ b/src/neetcode/linked-list/reversed-linked-list/solution.test.ts @@ -1,28 +1,5 @@ -import { ListNode, reverseList } from './solution'; - -const createList = (values: number[]): ListNode | null => { - const dummy = new ListNode(); - let tail = dummy; - - for (const value of values) { - tail.next = new ListNode(value); - tail = tail.next; - } - - return dummy.next; -}; - -const listToArray = (head: ListNode | null): number[] => { - const values: number[] = []; - let current = head; - - while (current) { - values.push(current.val); - current = current.next; - } - - return values; -}; +import { createList, ListNode, listToArray } from '../common'; +import { reverseList } from './solution'; describe('Reversed Linked List | NeetCode | RoadMap | Testcases', () => { test('#1 Reverses a linked list', () => { diff --git a/src/neetcode/linked-list/reversed-linked-list/solution.ts b/src/neetcode/linked-list/reversed-linked-list/solution.ts index ff02d05..b518038 100644 --- a/src/neetcode/linked-list/reversed-linked-list/solution.ts +++ b/src/neetcode/linked-list/reversed-linked-list/solution.ts @@ -1,11 +1,4 @@ -export class ListNode { - val: number; - next: ListNode | null; - constructor(val = 0, next = null) { - this.val = val; - this.next = next; - } -} +import { ListNode } from '../common'; /** * @param {ListNode} head - the beginning of a singly linked list