leetcode

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit 023cdd3a0f8e6375e1a21008305b080cb60af61c
parent fe8e30e5f0b01c424cb09d05270b3e7d56b662fe
Author: ling0x <ling0x@users.noreply.github.com>
Date:   Sun,  6 Sep 2026 18:03:21 +0100

linked list cycles

Diffstat:
Msrc/lib.rs | 1+
Asrc/linked_list/linked_list_cycle.rs | 13+++++++++++++
Asrc/linked_list/mod.rs | 1+
Ats/.gitignore | 1+
Ats/package-lock.json | 408+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ats/package.json | 14++++++++++++++
Ats/src/linked_list/-1, | 2++
Ats/src/linked_list/index.ts | 1+
Ats/src/linked_list/linkedListCycle.test.ts | 47+++++++++++++++++++++++++++++++++++++++++++++++
Ats/src/linked_list/linkedListCycle.ts | 239+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ats/tsconfig.json | 14++++++++++++++
11 files changed, 741 insertions(+), 0 deletions(-)

diff --git a/src/lib.rs b/src/lib.rs @@ -1,5 +1,6 @@ pub mod array; pub mod hash_table; +pub mod linked_list; #[cfg(test)] pub mod test_utils; diff --git a/src/linked_list/linked_list_cycle.rs b/src/linked_list/linked_list_cycle.rs @@ -0,0 +1,13 @@ +//! Given head, the head of a linked list, determine if the linked list has +//! a cycle in it. +//! +//! There is a cycle in a linked list if there is some node in the list that +//! can be reached again by continuously following the next pointer. +//! Internally, pos is used to denote the index of the node that tail's next +//! pointer is connected to. Note that pos is not passed as a parameter. +//! +//! Return true if there is a cycle in the linked list. Otherwise, return false. + +fn solution_1() -> bool { + true +} diff --git a/src/linked_list/mod.rs b/src/linked_list/mod.rs @@ -0,0 +1 @@ +pub mod linked_list_cycle; diff --git a/ts/.gitignore b/ts/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/ts/package-lock.json b/ts/package-lock.json @@ -0,0 +1,408 @@ +{ + "name": "leetcode-ts", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "leetcode-ts", + "version": "0.1.0", + "devDependencies": { + "@types/node": "*", + "typescript": "*" + } + }, + "node_modules/@types/node": { + "version": "26.1.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-26.1.1.tgz", + "integrity": "sha512-nxAkRSVkN1Y0JC1W8ky/fTfkGsMmcrRsbx+3XoZE+rMOX71kLYTV7fLXpqud1GpbpP5TuffXFqfX7fH2GgZREw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~8.3.0" + } + }, + "node_modules/@typescript/typescript-aix-ppc64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-aix-ppc64/-/typescript-aix-ppc64-7.0.2.tgz", + "integrity": "sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-darwin-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-darwin-arm64/-/typescript-darwin-arm64-7.0.2.tgz", + "integrity": "sha512-gowzar9MwS/aRWp6f3a4KUqzRjAZjOsmGNCM6LcTgXum+dBfgsBVMN+AgvOCCbguXyick6LJhpBszxMebJ8syA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-darwin-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-darwin-x64/-/typescript-darwin-x64-7.0.2.tgz", + "integrity": "sha512-SZ9xZInqApNlNGc9s0W1VSsktYSOe9cFqNOIqmN1Gs8SmkjKZYFt017G4VwPxASInODuAdbTW7sXiFUf893RgA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-freebsd-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-freebsd-arm64/-/typescript-freebsd-arm64-7.0.2.tgz", + "integrity": "sha512-W5NH4y/J0plIIS5b2xvTEkU7JFxyqdMAOgf+Ilhl0vHQXKO5dZoxd+C/jEtq56c4F3wk71RB4BMRQ2XdI+bwYQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-freebsd-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-freebsd-x64/-/typescript-freebsd-x64-7.0.2.tgz", + "integrity": "sha512-UMGDx5sTpzNw3WiPebH7l90IWfJggEd+egHt/q6p7/Cm3zqoV7VxkGXt+3DxPIw8CcmvAB0j3sVVfbhX+M4Tpw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-arm": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-arm/-/typescript-linux-arm-7.0.2.tgz", + "integrity": "sha512-gffT3xPz9sR7j/YJExkyPntrI0P2EP9XbOyWzth2/Gs0RstK+90RBcO0ncXoXy/beYll1SXw846Nf2zdnEz0QQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-arm64/-/typescript-linux-arm64-7.0.2.tgz", + "integrity": "sha512-Qh4eU4/y3yDjnfjjyPYihMj5/ODIlmt+Bzu17OI+fiSRDW57QmU5SiN63exPRNJPKUzcc1INa1NXdrJ+MqHjUQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-loong64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-loong64/-/typescript-linux-loong64-7.0.2.tgz", + "integrity": "sha512-uEHck9i8hoAzXPiYRib1O7miOnz23SxIeVl6F4LXox+qov1K35jHcEW6VHKvZI+pyvl7fZEP4MCU5LYvIq1GuQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-mips64el": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-mips64el/-/typescript-linux-mips64el-7.0.2.tgz", + "integrity": "sha512-R4KvAMnE43W5Qeqb0Ly56O3mWMWIAgsMyz36DCaycd5nbg/9kzm0liw3JocfRqyJY0KPmzFjbswozXyW0DnIYA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-ppc64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-ppc64/-/typescript-linux-ppc64-7.0.2.tgz", + "integrity": "sha512-DORx5b3sd/4S7eayxm4FQv+A7CrkUIGRaHiwI8oiHTAI1fAPWhF4J0vAlkC8biAlHSVVwxMQ3tjZ2/DVbnQiiA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-riscv64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-riscv64/-/typescript-linux-riscv64-7.0.2.tgz", + "integrity": "sha512-wf0jqEDOjrPRnKwYRyyJDRo11KMbvMFrU+q4zqKyChODBzvlkbhNQfKvLxQCcwTpdDaXSHZTVuh0JoCrKCUMHQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-s390x": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-s390x/-/typescript-linux-s390x-7.0.2.tgz", + "integrity": "sha512-IkwJc3L7yhytWd/ewjyxNDfOmswCm9GWMJT/ue/dU4aZNbwZeYAetq42VyLmsmSjvoX7z74X6ZaYCtzAr0EuGw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-linux-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-linux-x64/-/typescript-linux-x64-7.0.2.tgz", + "integrity": "sha512-EYdf2cNg7rgCWJnxCdJ+F3V39O8ihb37eHAu1LK8oAFizgTQbPOK7zHHXbPt8rX24COqODXeI3sIf0fCXG7H/A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-netbsd-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-netbsd-arm64/-/typescript-netbsd-arm64-7.0.2.tgz", + "integrity": "sha512-+polYF4MF04aPpO5FTkHran9yUQDSXqy5GiSDKpsll5jy3l3+g9QLhpf39T+ePtefhXLOGrLl0QIjkQP6VnelA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-netbsd-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-netbsd-x64/-/typescript-netbsd-x64-7.0.2.tgz", + "integrity": "sha512-8YIT0EHM/3dq10ZOVF/A7pc/YSMtbcecct4rWtexrnSCHOPcpC2KTLXfTCR6vDpnSiY12heNb1GiN/wu+T/FyA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-openbsd-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-openbsd-arm64/-/typescript-openbsd-arm64-7.0.2.tgz", + "integrity": "sha512-APT8+ClYnuYm1u9+kgGXoMj2VzWzcymwh2gNSQVySHfkRDGOTVkoWLjCmOQSaO+PoqQ57B0flRp9SA+7GnnkzQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-openbsd-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-openbsd-x64/-/typescript-openbsd-x64-7.0.2.tgz", + "integrity": "sha512-yX7s+Q0Dln0Dt9tEzZsAjXXR/+ytBM7AlglaqyeMPxQszJ1JhlJdZ6jLA+IzldHtflX81em7lDao1xXu+aRRkg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-sunos-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-sunos-x64/-/typescript-sunos-x64-7.0.2.tgz", + "integrity": "sha512-dLJDGaLZ1D4HPQn62u1n8mBDkJREwMsAkCdkwd4Ieqw+x3TUyTsqY0YiBCtE6H6OzzgGk3iuZ3vFWRS+E8/d1g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-win32-arm64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-win32-arm64/-/typescript-win32-arm64-7.0.2.tgz", + "integrity": "sha512-Gyl1Vy6OsWesLzmq+EP0Fb7b4Nid5232AvcA2SFcdYreldpNtYFFofPjnt62y9hQy7VTaZp65ICJjuAQRaVcIQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/@typescript/typescript-win32-x64": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript/typescript-win32-x64/-/typescript-win32-x64-7.0.2.tgz", + "integrity": "sha512-0BQ3HkAHHlKLSp1qRvf3SUhGpGsDuhB/jgFw75guyqbxJqEaS0Cw/VFO8i2nHglJUzQCRtMMR/IBAKE3ETMC4g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/typescript": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-7.0.2.tgz", + "integrity": "sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc" + }, + "engines": { + "node": ">=16.20.0" + }, + "optionalDependencies": { + "@typescript/typescript-aix-ppc64": "7.0.2", + "@typescript/typescript-darwin-arm64": "7.0.2", + "@typescript/typescript-darwin-x64": "7.0.2", + "@typescript/typescript-freebsd-arm64": "7.0.2", + "@typescript/typescript-freebsd-x64": "7.0.2", + "@typescript/typescript-linux-arm": "7.0.2", + "@typescript/typescript-linux-arm64": "7.0.2", + "@typescript/typescript-linux-loong64": "7.0.2", + "@typescript/typescript-linux-mips64el": "7.0.2", + "@typescript/typescript-linux-ppc64": "7.0.2", + "@typescript/typescript-linux-riscv64": "7.0.2", + "@typescript/typescript-linux-s390x": "7.0.2", + "@typescript/typescript-linux-x64": "7.0.2", + "@typescript/typescript-netbsd-arm64": "7.0.2", + "@typescript/typescript-netbsd-x64": "7.0.2", + "@typescript/typescript-openbsd-arm64": "7.0.2", + "@typescript/typescript-openbsd-x64": "7.0.2", + "@typescript/typescript-sunos-x64": "7.0.2", + "@typescript/typescript-win32-arm64": "7.0.2", + "@typescript/typescript-win32-x64": "7.0.2" + } + }, + "node_modules/undici-types": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.3.0.tgz", + "integrity": "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==", + "dev": true, + "license": "MIT" + } + } +} diff --git a/ts/package.json b/ts/package.json @@ -0,0 +1,14 @@ +{ + "name": "leetcode-ts", + "version": "0.1.0", + "private": true, + "type": "module", + "scripts": { + "test": "node --test", + "typecheck": "tsc --noEmit" + }, + "devDependencies": { + "typescript": "*", + "@types/node": "*" + } +} diff --git a/ts/src/linked_list/-1, b/ts/src/linked_list/-1, @@ -0,0 +1,2 @@ + + diff --git a/ts/src/linked_list/index.ts b/ts/src/linked_list/index.ts @@ -0,0 +1 @@ +export * from "./linkedListCycle.ts"; diff --git a/ts/src/linked_list/linkedListCycle.test.ts b/ts/src/linked_list/linkedListCycle.test.ts @@ -0,0 +1,47 @@ +import { test } from "node:test"; +import assert from "node:assert/strict"; + +import { buildList, solution3, type ListNode } from "./linkedListCycle.ts"; + +interface CycleCase { + name: string; + values: number[]; + pos: number; // index the tail links back to, or -1 for no cycle + expected: boolean; +} + +function fullCases(): CycleCase[] { + return [ + { name: "case_1", values: [3, 2, 0, -4], pos: 1, expected: true }, + { name: "case_2", values: [1, 2], pos: 0, expected: true }, + { name: "case_3", values: [1], pos: -1, expected: false }, + { name: "case_4", values: [], pos: -1, expected: false }, + { name: "case_5", values: [1, 2], pos: -1, expected: false }, + { + name: "case_6", + values: [ + -21, 10, 17, 8, 4, 26, 5, 35, 33, -7, -16, 27, -12, 6, 29, -12, 5, 9, + 20, 14, 14, 2, 13, -24, 21, 23, -21, 5, + ], + pos: -1, + expected: false, + }, + { name: "case_7", values: [1, 1, 1, 1], pos: -1, expected: false }, + ]; +} + +function runSolverCases( + solverName: string, + solver: (head: ListNode | null) => boolean, + cases: CycleCase[], +): void { + for (const c of cases) { + test(`${solverName}_${c.name}`, () => { + const head = buildList(c.values, c.pos); + assert.equal(solver(head), c.expected); + }); + } +} + +// runSolverCases("solution1", solution1, fullCases()); +runSolverCases("solution3", solution3, fullCases()); diff --git a/ts/src/linked_list/linkedListCycle.ts b/ts/src/linked_list/linkedListCycle.ts @@ -0,0 +1,239 @@ +/** + * Given head, the head of a linked list, determine if the linked list + * has a cycle in it. + * + * There is a cycle in a linked list if there is some node in the list + * that can be reached again by continuously following the next pointer. + * Internally, pos is used to denote the index of the node that tail's + * next pointer is connected to. Note that pos is not passed as a + * parameter. + * + * Return true if there is a cycle in the linked list. Otherwise, + * return false. + */ + +export class ListNode { + val: number; + next: ListNode | null; + constructor(val?: number, next?: ListNode | null) { + this.val = val === undefined ? 0 : val; + this.next = next === undefined ? null : next; + } +} + +/** + * Build a linked list from `values`. If `pos >= 0`, the tail's `next` is + * connected back to the node at index `pos` to form a cycle. `pos = -1` + * leaves the list acyclic. Returns the head (or null for an empty list). + */ +export function buildList(values: number[], pos: number): ListNode | null { + if (values.length === 0) return null; + + const nodes = values.map((v) => new ListNode(v)); + for (let i = 0; i < nodes.length - 1; i++) { + nodes[i].next = nodes[i + 1]; + } + if (pos >= 0) { + nodes[nodes.length - 1].next = nodes[pos]; + } + return nodes[0]; +} + +/** + * Definition for singly-linked list. + * class ListNode { + * val: number + * next: ListNode | null + * constructor(val?: number, next?: ListNode | null) { + * this.val = (val===undefined ? 0 : val) + * this.next = (next===undefined ? null : next) + * } + * } + */ + +// First attempt +// +// Failed (only check 1 at a time, which isnt enough) +// Failed on case: [-21,10,17,8,4,26,5,35,33,-7,-16,27,-12,6,29,-12,5,9,20,14, +// 14,2,13,-24,21,23,-21,5] (should be false) +export function solution1(head: ListNode | null): boolean { + if (!head) { + console.log("Head is empty. Return false"); + return false; + } + + let prev = null; + let current = head; + + while (current.next) { + if (!current.next.next) return false; + + console.log( + `Current: ${current.val}, next: ${current.next.val}, next's next ${current.next.next.val}`, + ); + + prev = current; + current = current.next; + + if (prev.next === current) { + console.log(`Prev's next: ${prev.next.val} === Current: ${current.val}`); + return true; + } + } + + return false; +} + +// Second attempt (two-pointer / sliding-window in same direction to detect +// lapse) +// +// Failed (only checks 2 at a time, which isnt enough) +// Failed on case [1,1,1,1] (should be false) +export function solution2(head: ListNode | null): boolean { + console.log("===================="); + console.log("Running test"); + + if (!head) { + console.log("Test is empty"); + return false; + } + + let next = head.next; + if (!next) { + console.log("Test only has 1 element, which isn't a cycle by default."); + return false; + } + + // Log the current head and the next head + console.log( + `Head ${head.val}, next ${next.val}, next's next ${next.next?.val}, next's next's next ${next.next?.next?.val}, next's next's next's next ${next.next?.next?.next?.val}, next's next's next's next's next ${next.next?.next?.next?.next?.val}`, + ); + + let sliding_window: { a: number; b: number }[] = [ + { a: head.val, b: next.val }, + ]; + + // While the list still has more vertices, keep looping through it + while (next) { + if (!next.next) { + console.log("The list has been exhausted without any cycles."); + return false; + } + + // If the next one exists, then add the next two to the sliding windows list + if (next.next) { + let next_pair: { a: number; b: number } = { + a: next.val, + b: next.next.val, + }; + console.log("Next pair: ", next_pair); + + const next_pair_already_exist = sliding_window.find( + (pair) => pair.a === next_pair.a && pair.b === next_pair.b, + ); + + if (next_pair_already_exist) { + console.log( + "Sliding window list already includes the next two pairs -> cycle detected", + ); + return true; + } + + sliding_window.push(next_pair); + + // move to the next one + next = next.next; + } + + console.log("Current state of the sliding Window: ", sliding_window); + } + + console.log("Not a cycle"); + return false; +} + +// Third attempt (need a verification step to verify that not only the pair +// exists but also is not terminating, if any pair terminates the list, then +// its not a cycle by default - we basically need a proof that the list doesn't +// terminate, even though the pairs lapse/repeat in the list) +// +// Success (Runtime: 1333ms, Memory: 63.33MB) +export function solution3(head: ListNode | null): boolean { + console.log("===================="); + console.log("Running test"); + + if (!head) { + console.log("Test is empty"); + return false; + } + + let next = head.next; + if (!next) { + console.log("Test only has 1 element, which isn't a cycle by default."); + return false; + } + + // Log the current head and the next head + console.log( + `Head ${head.val}, next ${next.val}, next's next ${next.next?.val}, next's next's next ${next.next?.next?.val}, next's next's next's next ${next.next?.next?.next?.val}, next's next's next's next's next ${next.next?.next?.next?.next?.val}`, + ); + + let index = 0; + let sliding_window: { + a: { val: number; pos: number }; + b: { val: number; pos: number }; + }[] = [ + { + a: { val: head.val, pos: index }, + b: { val: next.val, pos: index + 1 }, + }, + ]; + + // While the list still has more vertices, keep looping through it + while (next) { + // Increment the index counter + index += 1; + + if (!next.next) { + console.log("The list terminates without any cycles."); + return false; + } + + // If the next one exists, then add the next two to the sliding windows list + if (next.next) { + let next_pair: { + a: { val: number; pos: number }; + b: { val: number; pos: number }; + } = { + a: { val: next.val, pos: index }, + b: { val: next.next.val, pos: index + 1 }, + }; + console.log("Next pair: ", next_pair); + + const next_pair_already_exist = sliding_window.findLast( + (pair) => + pair.a.val === next_pair.a.val && pair.b.val === next_pair.b.val, + ); + + if (next_pair_already_exist) { + console.log("Sliding window list already includes the next two pairs"); + // Check if the next pair is terminating + if (next.next.next && next.next.next.next) { + return true; + } else { + return false; + } + } + + sliding_window.push(next_pair); + + // move to the next one + next = next.next; + } + + console.log("Current state of the sliding Window: ", sliding_window); + } + + console.log("Not a cycle"); + return false; +} diff --git a/ts/tsconfig.json b/ts/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "target": "ESNext", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "rewriteRelativeImportExtensions": true, + "verbatimModuleSyntax": true, + "strict": true, + "noEmit": true, + "skipLibCheck": true, + "types": ["node"] + }, + "include": ["src"] +}