├── .github └── workflows │ └── nodejs.yml ├── .gitignore ├── analyze ├── build.sh ├── package.json ├── src │ ├── leetcode │ │ ├── explore.md │ │ ├── explore.ts │ │ ├── fetch-problems-cn.ts │ │ ├── fetch-problems-en.ts │ │ ├── urls-cn.ts │ │ └── urls-en.ts │ ├── readme │ │ ├── readme-maker.ts │ │ └── readme-skeleton.md │ ├── types.ts │ ├── update-repo │ │ ├── bar.ts │ │ ├── gen-desc.ts │ │ └── index.ts │ └── util │ │ └── search-solutions.ts ├── tsconfig.json └── yarn.lock ├── js ├── .eslintrc.json ├── .prettierrc ├── analyze │ └── analyze.ts ├── helper │ ├── parse-accepted.ts │ ├── sleep.ts │ ├── swap.ts │ ├── test-helper.ts │ └── types.ts ├── jest-resolver-fix.js ├── jest.config.js ├── legacy-js │ ├── 134.gas-station │ │ └── solution.js │ ├── 172.factorial-trailing-zeroes │ │ └── solution.js │ ├── 219.contains-duplicate-ii │ │ └── solution.js │ ├── 220.contains-duplicate-iii │ │ └── solution.js │ ├── 223.rectangle-area │ │ └── solution.js │ ├── 226.invert-binary-tree │ │ └── solution.js │ ├── 263.ugly-number │ │ └── solution.js │ ├── 289.game-of-life │ │ └── solution.js │ ├── 342.power-of-four │ │ └── solution.js │ ├── 371.sum-of-two-integers │ │ └── solution.js │ ├── 435.non-overlapping-intervals │ │ └── solution.js │ ├── 437.path-sum-iii │ │ └── solution.js │ ├── 448.find-all-numbers-disappeared-in-an-array │ │ └── solution.js │ ├── 455.assign-cookies │ │ └── solution.js │ ├── 461.hamming-distance │ │ └── solution.js │ ├── 5.longest-palindromic-substring │ │ └── solution.js │ ├── 538.convert-bst-to-greater-tree │ │ └── solution.js │ ├── 575.distribute-candies │ │ └── solution.js │ ├── 581.shortest-unsorted-continuous-subarray │ │ └── solution.js │ └── 617.merge-two-binary-trees │ │ └── solution.js ├── package.json ├── problems │ ├── 1.two-sum │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 101.symmetric-tree │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 104.maximum-depth-of-binary-tree │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 112.path-sum │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 113.path-sum-ii │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 118.pascals-triangle │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 119.pascals-triangle-ii │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 121.best-time-to-buy-and-sell-stock │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 122.best-time-to-buy-and-sell-stock-ii │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 125.valid-palindrome │ │ ├── do.test.ts │ │ ├── solution-fancy.ts │ │ └── solution.ts │ ├── 133.clone-graph │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 136.single-number │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 138.copy-list-with-random-pointer │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 14.longest-common-prefix │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 141.linked-list-cycle │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 142.linked-list-cycle-ii │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 150.evaluate-reverse-polish-notation │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 151.reverse-words-in-a-string │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 153.find-minimum-in-rotated-sorted-array │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 154.find-minimum-in-rotated-sorted-array-ii │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 155.min-stack │ │ ├── do.test.ts │ │ ├── solution-class.ts │ │ ├── solution.ts │ │ └── types.d.ts │ ├── 160.intersection-of-two-linked-lists │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 162.find-peak-element │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 167.two-sum-ii-input-array-is-sorted │ │ ├── do.test.ts │ │ ├── readme.md │ │ └── solution.ts │ ├── 189.rotate-array │ │ ├── do.test.ts │ │ ├── solution-map.ts │ │ ├── solution-pointer.ts │ │ └── solution.ts │ ├── 19.remove-nth-node-from-end-of-list │ │ ├── do.test.ts │ │ ├── solution-check-input.ts │ │ └── solution.ts │ ├── 2.add-two-numbers │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 20.valid-parentheses │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 200.number-of-islands │ │ ├── do.test.ts │ │ ├── solution-bfs.ts │ │ ├── solution.ts │ │ └── types.d.ts │ ├── 203.remove-linked-list-elements │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 206.reverse-linked-list │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 209.minimum-size-subarray-sum │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 21.merge-two-sorted-lists │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 217.contains-duplicate │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 225.implement-stack-using-queues │ │ ├── do.test.ts │ │ ├── solution-class.ts │ │ ├── solution.ts │ │ └── types.d.ts │ ├── 232.implement-queue-using-stacks │ │ ├── do.test.ts │ │ ├── solution-class.ts │ │ ├── solution.ts │ │ └── types.d.ts │ ├── 234.palindrome-linked-list │ │ ├── do.test.ts │ │ ├── solution-unsafe.ts │ │ └── solution.ts │ ├── 237.delete-node-in-a-linked-list │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 24.swap-nodes-in-pairs │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 242.valid-anagram │ │ ├── do.test.ts │ │ ├── solution-fancy.ts │ │ └── solution.ts │ ├── 26.remove-duplicates-from-sorted-array │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 27.remove-element │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 278.first-bad-version │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 279.perfect-squares │ │ ├── do.test.ts │ │ ├── solution-bfs-opts.ts │ │ ├── solution-bfs.ts │ │ └── solution.ts │ ├── 28.implement-str-str │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 283.move-zeroes │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 287.find-the-duplicate-number │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 31.next-permutation │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 328.odd-even-linked-list │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 33.search-in-rotated-sorted-array │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 331.verify-preorder-serialization-of-a-binary-tree │ │ ├── do.test.ts │ │ ├── solution-wipe.ts │ │ └── solution.ts │ ├── 34.find-first-and-last-position-of-element-in-sorted-array │ │ ├── do.test.ts │ │ ├── solution-semi-bs.ts │ │ └── solution.ts │ ├── 344.reverse-string │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 349.intersection-of-two-arrays │ │ ├── do.test.ts │ │ ├── solution-two-pointer.ts │ │ ├── solution.ts │ │ └── todo.md │ ├── 350.intersection-of-two-arrays-ii │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 36.valid-sudoku │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 367.valid-perfect-square │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 37.sudoku-solver │ │ ├── do.test.ts │ │ ├── solution-pick-and-check.ts │ │ └── solution.ts │ ├── 374.guess-number-higher-or-lower │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 38.count-and-say │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 387.first-unique-character-in-a-string │ │ ├── do.test.ts │ │ ├── solution-last-index.ts │ │ ├── solution-map.ts │ │ └── solution.ts │ ├── 394.decode-string │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 4.median-of-two-sorted-arrays │ │ ├── do.test.ts │ │ └── readme.md │ ├── 430.flatten-a-multilevel-doubly-linked-list │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 48.rotate-image │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 485.max-consecutive-ones │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 494.target-sum │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 498.diagonal-traverse │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 5.longest-palindromic-substring │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 50.pow-x-n │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 509.fibonacci-number │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 51.n-queens │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 52.n-queens-ii │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 539.minimum-time-difference │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 54.spiral-matrix │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 542.01-matrix │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 557.reverse-words-in-a-string-iii │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 561.array-partition-i │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 59.spiral-matrix-ii │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 61.rotate-list │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 622.design-circular-queue │ │ ├── do.test.ts │ │ ├── solution-class.ts │ │ ├── solution.ts │ │ └── types.d.ts │ ├── 658.find-k-closest-elements │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 66.plus-one │ │ ├── do.test.ts │ │ ├── solution.ts │ │ └── solution2.ts │ ├── 67.add-binary │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 69.sqrt-x │ │ ├── do.test.ts │ │ ├── solution-newton-int.ts │ │ └── solution.ts │ ├── 7.reverse-integer │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 70.climbing-stairs │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 700.search-in-a-binary-search-tree │ │ ├── do.test.ts │ │ ├── solution-bfs.ts │ │ └── solution.ts │ ├── 704.binary-search │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 707.design-linked-list │ │ ├── do.test.ts │ │ ├── solution-singly-dummy.ts │ │ ├── solution-singly-head-tail.ts │ │ ├── solution.ts │ │ └── types.d.ts │ ├── 724.find-pivot-index │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 733.flood-fill │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 739.daily-temperatures │ │ ├── do.test.ts │ │ ├── solution-simple.ts │ │ └── solution.ts │ ├── 744.find-smallest-letter-greater-than-target │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 747.largest-number-at-least-twice-of-others │ │ ├── do.test.ts │ │ ├── solution-2.ts │ │ └── solution.ts │ ├── 752.open-the-lock │ │ ├── do.test.ts │ │ ├── solution-naive.ts │ │ ├── solution-normal.ts │ │ └── solution.ts │ ├── 779.k-th-symbol-in-grammar │ │ ├── do.test.ts │ │ ├── solution-readable.ts │ │ └── solution.ts │ ├── 8.string-to-integer-atoi │ │ ├── do.test.ts │ │ ├── solution-fancy.ts │ │ └── solution.ts │ ├── 80.remove-duplicates-from-sorted-array-ii │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 82.remove-duplicates-from-sorted-list-ii │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 83.remove-duplicates-from-sorted-list │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 841.keys-and-rooms │ │ ├── do.test.ts │ │ └── solution.ts │ ├── 92.reverse-linked-list-ii │ │ ├── do.test.ts │ │ ├── solution-no-dummy.ts │ │ └── solution.ts │ ├── 94.binary-tree-inorder-traversal │ │ ├── do.test.ts │ │ ├── solution-recursive.ts │ │ └── solution.ts │ ├── 95.unique-binary-search-trees-ii │ │ ├── do.test.ts │ │ └── solution.ts │ └── 98.validate-binary-search-tree │ │ ├── do.test.ts │ │ ├── solution-fancy-inorder.ts │ │ ├── solution-recursion-with-range.ts │ │ └── solution.ts ├── readme.md ├── structures │ ├── graph │ │ ├── graph-node.ts │ │ ├── graph-to-array.test.ts │ │ └── graph-to-array.ts │ ├── linked-list │ │ ├── list-node.ts │ │ ├── list-to-array.test.ts │ │ └── list-to-array.ts │ └── tree │ │ ├── tree-node.ts │ │ ├── tree-to-array.test.ts │ │ └── tree-to-array.ts ├── tsconfig-build.json ├── tsconfig.json └── yarn.lock ├── note └── study-note.md └── readme.md /.github/workflows/nodejs.yml: -------------------------------------------------------------------------------- 1 | name: update-repo 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | 7 | jobs: 8 | update-repo: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v1 12 | - uses: borales/actions-yarn@v2.0.0 13 | - run: | 14 | cd analyze 15 | yarn 16 | yarn update-repo 17 | env: 18 | REPO_MOD_TOKEN: ${{ secrets.REPO_MOD_TOKEN }} 19 | GH_REPO: ${{ secrets.GH_REPO }} 20 | -------------------------------------------------------------------------------- /analyze/build.sh: -------------------------------------------------------------------------------- 1 | cd src/readme 2 | ts-node readme-maker.ts 3 | cd ../../ 4 | npx doctoc ../readme.md 5 | npx prettier --write ../readme.md 6 | -------------------------------------------------------------------------------- /analyze/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "readme": "sh build.sh", 4 | "update-repo": "ts-node src/update-repo/index.ts" 5 | }, 6 | "devDependencies": { 7 | "@types/glob": "^7.1.1", 8 | "@types/node": "^13.11.0", 9 | "@types/ramda": "^0.27.3", 10 | "doctoc": "^1.4.0", 11 | "glob": "^7.1.6", 12 | "prettier": "^2.0.3", 13 | "ramda": "^0.27.0", 14 | "ts-node": "^8.9.0", 15 | "typescript": "^3.8.3" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /analyze/src/types.ts: -------------------------------------------------------------------------------- 1 | type Index = string; 2 | type Title = string; 3 | export type Difficulty = 'Easy' | 'Medium' | 'Hard' | '简单' | '中等' | '困难'; 4 | type Acceptance = string; 5 | type Locked = 'LOCKED'; 6 | 7 | export const LOCKED = 'LOCKED'; 8 | 9 | export type Problem = [Index, Title, Difficulty, Acceptance, Locked?]; 10 | 11 | export type UrlList = [string, string][]; 12 | -------------------------------------------------------------------------------- /analyze/src/update-repo/bar.ts: -------------------------------------------------------------------------------- 1 | export const generateBarChart = (percent: number, size: number) => { 2 | const syms = '░▏▎▍▌▋▊▉█'; 3 | 4 | const frac = Math.floor((size * 8 * percent) / 100); 5 | const barsFull = Math.floor(frac / 8); 6 | if (barsFull >= size) { 7 | return syms.substring(8, 9).repeat(size); 8 | } 9 | const semi = frac % 8; 10 | 11 | return [syms.substring(8, 9).repeat(barsFull), syms.substring(semi, semi + 1)] 12 | .join('') 13 | .padEnd(size, syms.substring(0, 1)); 14 | }; 15 | -------------------------------------------------------------------------------- /analyze/src/update-repo/gen-desc.ts: -------------------------------------------------------------------------------- 1 | import { searchLangSolutions } from '../util/search-solutions'; 2 | import { problemsEn } from '../leetcode/fetch-problems-en'; 3 | import { generateBarChart } from './bar'; 4 | 5 | const curLang = 'ts'; 6 | 7 | const solCount = Object.keys(searchLangSolutions(curLang)).length; 8 | const probCount = problemsEn.length; 9 | const bar = generateBarChart((solCount * 100) / probCount, 16); 10 | 11 | export const genDesc = () => `progress (${curLang}): ${bar} ${solCount}/${probCount}`; 12 | -------------------------------------------------------------------------------- /analyze/src/update-repo/index.ts: -------------------------------------------------------------------------------- 1 | import { execSync } from 'child_process'; 2 | import { genDesc } from './gen-desc'; 3 | 4 | const { REPO_MOD_TOKEN: token, GH_REPO: repo } = process.env; 5 | 6 | if (token !== undefined && repo !== undefined) { 7 | execSync( 8 | ` 9 | curl -H "Authorization: token ${token}" \ 10 | --request PATCH \ 11 | --data '{"description":"${genDesc()}"}' \ 12 | https://api.github.com/repos/${repo} 13 | `, 14 | { stdio: 'inherit' }, 15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /analyze/src/util/search-solutions.ts: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | import glob from 'glob'; 3 | 4 | const relPath = path.resolve(__dirname, '../../..'); 5 | 6 | export const solutionFilePatterns: Record = { 7 | ts: ['js/problems/', 'solution*.ts'], 8 | }; 9 | 10 | export const searchLangSolutions = (lang: string): Record => { 11 | const [folder, pattern] = solutionFilePatterns[lang]; 12 | const repoFolder = path.join(relPath, folder); 13 | 14 | return glob 15 | .sync(path.join(repoFolder, '*', pattern)) 16 | .map((e) => path.relative(repoFolder, e)) 17 | .reduce((a: Record, e) => { 18 | const no = e.match(/\d+(?=\.)/)![0]; 19 | a[no] = a[no] || []; 20 | a[no].unshift(e); 21 | return a; 22 | }, {}); 23 | }; 24 | -------------------------------------------------------------------------------- /analyze/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES6", 4 | "lib": ["ES2020"], 5 | "strict": true, 6 | "esModuleInterop": true, 7 | "moduleResolution": "node" 8 | }, 9 | "exclude": ["node_modules"] 10 | } 11 | -------------------------------------------------------------------------------- /js/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "@typescript-eslint/parser", 3 | "parserOptions": { 4 | "ecmaVersion": 2020, 5 | "sourceType": "module", 6 | "ecmaFeatures": { 7 | "modules": true 8 | } 9 | }, 10 | "plugins": ["@typescript-eslint"] 11 | } 12 | -------------------------------------------------------------------------------- /js/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "always", 3 | "printWidth": 100, 4 | "singleQuote": true, 5 | "trailingComma": "all", 6 | "tabWidth": 2, 7 | "quoteProps": "consistent", 8 | "semi": true, 9 | "useTabs": false, 10 | "overrides": [ 11 | { 12 | "files": "fetch-problems*", 13 | "options": { 14 | "printWidth": 140 15 | } 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /js/helper/parse-accepted.ts: -------------------------------------------------------------------------------- 1 | export const parseAccepted = (str: string): string => { 2 | const ms = str.match(/cases passed \((.*?)\)/)![1]; 3 | const runbeat = str.match(/runtime beats (.*)? of/)![1]; 4 | const rambeat = str.match(/usage beats (.*)? of/)![1]; 5 | const ram = str.match(/submissions \((.*?)\)/)![1]; 6 | 7 | const result = [ms, runbeat, ram, rambeat].map((e) => `'${e}'`).join(', '); 8 | const printResult = `[${result}]`; 9 | 10 | console.log('\n', printResult, '\n'); 11 | 12 | return printResult; 13 | }; 14 | -------------------------------------------------------------------------------- /js/helper/sleep.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * sync sleep by miliseconds 3 | */ 4 | export const sleep = (n: number = 1000): void => { 5 | const s = Date.now(); 6 | while (Date.now() < s + n) {} 7 | }; 8 | -------------------------------------------------------------------------------- /js/helper/swap.ts: -------------------------------------------------------------------------------- 1 | const swap = (nums: unknown[], i: number, j: number): void => { 2 | const t = nums[i]; 3 | nums[i] = nums[j]; 4 | nums[j] = t; 5 | }; 6 | -------------------------------------------------------------------------------- /js/helper/types.ts: -------------------------------------------------------------------------------- 1 | export type LowerLetter = 2 | | 'a' 3 | | 'b' 4 | | 'c' 5 | | 'd' 6 | | 'e' 7 | | 'f' 8 | | 'g' 9 | | 'h' 10 | | 'i' 11 | | 'j' 12 | | 'k' 13 | | 'l' 14 | | 'm' 15 | | 'n' 16 | | 'o' 17 | | 'p' 18 | | 'q' 19 | | 'r' 20 | | 's' 21 | | 't' 22 | | 'u' 23 | | 'v' 24 | | 'w' 25 | | 'x' 26 | | 'y' 27 | | 'z'; 28 | 29 | export type Digit = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0; 30 | export type DigitStr = '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '0'; 31 | -------------------------------------------------------------------------------- /js/jest-resolver-fix.js: -------------------------------------------------------------------------------- 1 | // * let jest prefer `solution.ts` instead of `solution.js` 2 | // * origin config maybe from `ts-jest` 3 | 4 | module.exports = (request, options) => { 5 | const { defaultResolver } = options; 6 | 7 | // const oldExtensions = ['.js', '.json', '.jsx', '.ts', '.tsx', '.node']; 8 | const newExtensions = ['.ts', '.tsx', '.node', '.js', '.json', '.jsx']; 9 | 10 | const newOptions = { ...options, extensions: newExtensions }; 11 | 12 | return defaultResolver(request, newOptions); 13 | }; 14 | -------------------------------------------------------------------------------- /js/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'ts-jest', 3 | testEnvironment: 'node', 4 | verbose: true, 5 | collectCoverage: true, 6 | resolver: `./jest-resolver-fix.js`, 7 | }; 8 | -------------------------------------------------------------------------------- /js/legacy-js/134.gas-station/solution.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=134 lang=javascript 3 | * 4 | * [134] Gas Station 5 | */ 6 | /** 7 | * @param {number[]} gas 8 | * @param {number[]} cost 9 | * @return {number} 10 | */ 11 | var canCompleteCircuit = function(gas, cost) { 12 | if (gas.reduce((a, e) => a + e) < cost.reduce((a, e) => a + e)) return -1; 13 | 14 | let start = 0, 15 | carry = 0; 16 | for (let i = 0; i < gas.length; i++) { 17 | carry += gas[i] - cost[i]; 18 | if (carry < 0) { 19 | carry = 0; 20 | start = i + 1; 21 | } 22 | } 23 | 24 | console.warn('lcdebug 07-11 212611', '', start); 25 | return start; 26 | }; 27 | -------------------------------------------------------------------------------- /js/legacy-js/172.factorial-trailing-zeroes/solution.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=172 lang=javascript 3 | * 4 | * [172] Factorial Trailing Zeroes 5 | */ 6 | /** 7 | * @param {number} n 8 | * @return {number} 9 | */ 10 | var trailingZeroes = function(n) { 11 | let count = 0; 12 | while (n != 0) { 13 | n = ~~(n / 5); 14 | count += n; 15 | } 16 | return count; 17 | }; 18 | -------------------------------------------------------------------------------- /js/legacy-js/219.contains-duplicate-ii/solution.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=219 lang=javascript 3 | * 4 | * [219] Contains Duplicate II 5 | */ 6 | /** 7 | * @param {number[]} nums 8 | * @param {number} k 9 | * @return {boolean} 10 | */ 11 | var containsNearbyDuplicate = function(nums, k) { 12 | if (nums.length <= 1 || k < 1) return false; 13 | const map = new Map(); 14 | let l = 0; 15 | for (let i = 0; i < nums.length; i++) { 16 | if (i > k) { 17 | map.delete(nums[l]); 18 | l++; 19 | } 20 | if (map.has(nums[i])) return true; 21 | map.set(nums[i]); 22 | } 23 | return false; 24 | }; 25 | -------------------------------------------------------------------------------- /js/legacy-js/220.contains-duplicate-iii/solution.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=220 lang=javascript 3 | * 4 | * [220] Contains Duplicate III 5 | */ 6 | /** 7 | * @param {number[]} nums 8 | * @param {number} k 9 | * @param {number} t 10 | * @return {boolean} 11 | */ 12 | var containsNearbyAlmostDuplicate = function(nums, k, t) { 13 | if (nums.length <= 1 || k < 1 || t < 0) return false; 14 | 15 | const sub = []; 16 | for (let i = 0; i < nums.length; i++) { 17 | const e = nums[i]; 18 | sub.push(e); 19 | if (i > k) sub.shift(); 20 | for (let j = 0; j < sub.length - 1; j++) { 21 | if (Math.abs(e - sub[j]) <= t) return true; 22 | } 23 | } 24 | 25 | return false; 26 | }; 27 | -------------------------------------------------------------------------------- /js/legacy-js/223.rectangle-area/solution.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=223 lang=javascript 3 | * 4 | * [223] Rectangle Area 5 | */ 6 | /** 7 | * @param {number} A 8 | * @param {number} B 9 | * @param {number} C 10 | * @param {number} D 11 | * @param {number} E 12 | * @param {number} F 13 | * @param {number} G 14 | * @param {number} H 15 | * @return {number} 16 | */ 17 | var computeArea = function(A, B, C, D, E, F, G, H) { 18 | const d = (a, b) => Math.abs(a - b); 19 | const ii = (...arr) => { 20 | const intersect = d(arr[0], arr[1]) + d(arr[2], arr[3]) - (Math.max(...arr) - Math.min(...arr)); 21 | return intersect > 0 ? intersect : 0; 22 | }; 23 | return d(C, A) * d(D, B) + d(G, E) * d(H, F) - ii(A, C, E, G) * ii(B, D, F, H); 24 | }; 25 | -------------------------------------------------------------------------------- /js/legacy-js/226.invert-binary-tree/solution.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=226 lang=javascript 3 | * 4 | * [226] Invert Binary Tree 5 | */ 6 | /** 7 | * Definition for a binary tree node. 8 | * function TreeNode(val) { 9 | * this.val = val; 10 | * this.left = this.right = null; 11 | * } 12 | */ 13 | /** 14 | * @param {TreeNode} root 15 | * @return {TreeNode} 16 | */ 17 | var invertTree = function(root) { 18 | if (root === null) return null; 19 | const cacheLeft = root.left; 20 | root.left = invertTree(root.right); 21 | root.right = invertTree(cacheLeft); 22 | return root; 23 | }; 24 | -------------------------------------------------------------------------------- /js/legacy-js/263.ugly-number/solution.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=263 lang=javascript 3 | * 4 | * [263] Ugly Number 5 | */ 6 | /** 7 | * @param {number} num 8 | * @return {boolean} 9 | */ 10 | var isUgly = function(num) { 11 | if (num < 1) return false; 12 | 13 | while (~~(num / 2) === num / 2) num /= 2; 14 | while (~~(num / 3) === num / 3) num /= 3; 15 | while (~~(num / 5) === num / 5) num /= 5; 16 | 17 | return num === 1; 18 | }; 19 | -------------------------------------------------------------------------------- /js/legacy-js/342.power-of-four/solution.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=342 lang=javascript 3 | * 4 | * [342] Power of Four 5 | */ 6 | /** 7 | * @param {number} num 8 | * @return {boolean} 9 | */ 10 | var isPowerOfFour = function(num) { 11 | return /^1(00)*$/.test(num.toString(2)); 12 | }; 13 | -------------------------------------------------------------------------------- /js/legacy-js/371.sum-of-two-integers/solution.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=371 lang=javascript 3 | * 4 | * [371] Sum of Two Integers 5 | */ 6 | /** 7 | * @param {number} a 8 | * @param {number} b 9 | * @return {number} 10 | */ 11 | var getSum = function(a, b) { 12 | let carry; 13 | while (b) { 14 | carry = (a & b) << 1; 15 | a = a ^ b; 16 | b = carry; 17 | } 18 | 19 | return a; 20 | }; 21 | -------------------------------------------------------------------------------- /js/legacy-js/435.non-overlapping-intervals/solution.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=435 lang=javascript 3 | * 4 | * [435] Non-overlapping Intervals 5 | */ 6 | /** 7 | * @param {number[][]} intervals 8 | * @return {number} 9 | */ 10 | var eraseOverlapIntervals = function(intervals) { 11 | if (intervals.length < 2) return 0; 12 | intervals.sort(([a], [b]) => a - b); 13 | let end = intervals[0][1]; 14 | let count = 1; 15 | for (let i = 1; i < intervals.length; i++) { 16 | const e = intervals[i]; 17 | if (e[1] < end) { 18 | end = e[1]; 19 | } else if (end <= e[0]) { 20 | count++; 21 | end = e[1]; 22 | } 23 | } 24 | return intervals.length - count; 25 | }; 26 | -------------------------------------------------------------------------------- /js/legacy-js/437.path-sum-iii/solution.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=437 lang=javascript 3 | * 4 | * [437] Path Sum III 5 | */ 6 | /** 7 | * Definition for a binary tree node. 8 | * function TreeNode(val) { 9 | * this.val = val; 10 | * this.left = this.right = null; 11 | * } 12 | */ 13 | /** 14 | * @param {TreeNode} root 15 | * @param {number} sum 16 | * @return {number} 17 | */ 18 | var pathSum = function(root, sum) { 19 | let count = 0; 20 | 21 | const subway = (node) => { 22 | if (node === null) return; 23 | 24 | const { left: l, val: m, right: r } = node; 25 | if (m === sum) count += 1; 26 | const remain = sum - m; 27 | 28 | subway(l); 29 | subway(r); 30 | 31 | subwayPart(l, remain); 32 | subwayPart(r, remain); 33 | }; 34 | 35 | const subwayPart = (node, remain) => { 36 | if (node === null) return; 37 | const { left: l, val: m, right: r } = node; 38 | remain -= m; 39 | if (0 === remain) count += 1; 40 | subwayPart(l, remain); 41 | subwayPart(r, remain); 42 | }; 43 | 44 | subway(root, sum); 45 | 46 | return count; 47 | }; 48 | -------------------------------------------------------------------------------- /js/legacy-js/448.find-all-numbers-disappeared-in-an-array/solution.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=448 lang=javascript 3 | * 4 | * [448] Find All Numbers Disappeared in an Array 5 | */ 6 | /** 7 | * @param {number[]} nums 8 | * @return {number[]} 9 | */ 10 | var findDisappearedNumbers = function(nums) { 11 | nums.forEach((e) => { 12 | e = Math.abs(e) - 1; 13 | nums[e] > 0 && (nums[e] = -nums[e]); 14 | }); 15 | 16 | const miss = []; 17 | for (let i = 0; i < nums.length; i++) { 18 | nums[i] > 0 && miss.push(i + 1); 19 | } 20 | return miss; 21 | }; 22 | -------------------------------------------------------------------------------- /js/legacy-js/455.assign-cookies/solution.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=455 lang=javascript 3 | * 4 | * [455] Assign Cookies 5 | */ 6 | /** 7 | * @param {number[]} g 8 | * @param {number[]} s 9 | * @return {number} 10 | */ 11 | var findContentChildren = function(g, s) { 12 | g = g.sort((a, b) => b - a); 13 | s = s.sort((a, b) => b - a); 14 | 15 | let i = g.length - 1, 16 | j = s.length - 1; 17 | 18 | let count = 0; 19 | 20 | while (i >= 0 && j >= 0) { 21 | if (s[j] >= g[i]) { 22 | count += 1; 23 | j--; 24 | i--; 25 | } else { 26 | j--; 27 | } 28 | } 29 | return count; 30 | }; 31 | -------------------------------------------------------------------------------- /js/legacy-js/461.hamming-distance/solution.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=461 lang=javascript 3 | * 4 | * [461] Hamming Distance 5 | */ 6 | /** 7 | * @param {number} x 8 | * @param {number} y 9 | * @return {number} 10 | */ 11 | var hammingDistance = function(x, y) { 12 | x = x ^ y; 13 | let count = 0; 14 | while (x) { 15 | x % 2 && count++; 16 | x >>= 1; 17 | } 18 | return count; 19 | }; 20 | -------------------------------------------------------------------------------- /js/legacy-js/5.longest-palindromic-substring/solution.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=5 lang=javascript 3 | * 4 | * [5] Longest Palindromic Substring 5 | */ 6 | /** 7 | * @param {string} s 8 | * @return {string} 9 | */ 10 | var longestPalindrome = function(s) { 11 | // TODO, it's brute, try Manacher // seognil LC 2019/06/08 12 | if (!s.length) return ''; 13 | let max = s[0]; 14 | for (let i = 0; i < s.length; i++) { 15 | for (let even = 0; even < 2; even++) { 16 | let j = i, 17 | k = i + even; 18 | while (j >= 0 && s[j] == s[k]) { 19 | j--, k++; 20 | } 21 | if (k - j - 1 > max.length) max = s.substring(j + 1, k); 22 | } 23 | } 24 | 25 | return max; 26 | }; 27 | -------------------------------------------------------------------------------- /js/legacy-js/538.convert-bst-to-greater-tree/solution.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=538 lang=javascript 3 | * 4 | * [538] Convert BST to Greater Tree 5 | */ 6 | /** 7 | * Definition for a binary tree node. 8 | * function TreeNode(val) { 9 | * this.val = val; 10 | * this.left = this.right = null; 11 | * } 12 | */ 13 | /** 14 | * @param {TreeNode} root 15 | * @return {TreeNode} 16 | */ 17 | var convertBST = function(root) { 18 | const subway = (node, carry = 0) => { 19 | if (node === null) return 0; 20 | 21 | const r = subway(node.right, carry), 22 | m = node.val, 23 | l = subway(node.left, carry + m + r); 24 | 25 | node.val += carry + r; 26 | 27 | return r + m + l; 28 | }; 29 | 30 | subway(root); 31 | 32 | return root; 33 | }; 34 | -------------------------------------------------------------------------------- /js/legacy-js/575.distribute-candies/solution.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=575 lang=javascript 3 | * 4 | * [575] Distribute Candies 5 | */ 6 | /** 7 | * @param {number[]} candies 8 | * @return {number} 9 | */ 10 | var distributeCandies = function(candies) { 11 | return Math.min(new Set(candies).size, candies.length / 2); 12 | }; 13 | -------------------------------------------------------------------------------- /js/legacy-js/581.shortest-unsorted-continuous-subarray/solution.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=581 lang=javascript 3 | * 4 | * [581] Shortest Unsorted Continuous Subarray 5 | */ 6 | /** 7 | * @param {number[]} nums 8 | * @return {number} 9 | */ 10 | var findUnsortedSubarray = function(nums) { 11 | if (!nums || nums.length < 2) return 0; 12 | 13 | let subMin = Infinity, 14 | subMax = -Infinity, 15 | len = nums.length, 16 | last; 17 | 18 | for (let i = 0; i < len; i++) { 19 | const e = nums[i]; 20 | if (last > e) { 21 | subMin = Math.min(subMin, e); 22 | subMax = Math.max(subMax, last); 23 | } 24 | last = e; 25 | } 26 | 27 | // * not found peek 28 | if (subMin == Infinity) return 0; 29 | 30 | for (let i = 0; i < len; i++) { 31 | const e = nums[i]; 32 | if (e > subMin) { 33 | subMin = i; 34 | break; 35 | } 36 | } 37 | 38 | for (let i = len - 1; i > 0; i--) { 39 | const e = nums[i]; 40 | if (subMax > e) { 41 | subMax = i; 42 | break; 43 | } 44 | } 45 | 46 | return subMax - subMin + 1; 47 | }; 48 | -------------------------------------------------------------------------------- /js/legacy-js/617.merge-two-binary-trees/solution.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=617 lang=javascript 3 | * 4 | * [617] Merge Two Binary Trees 5 | */ 6 | /** 7 | * Definition for a binary tree node. 8 | * function TreeNode(val) { 9 | * this.val = val; 10 | * this.left = this.right = null; 11 | * } 12 | */ 13 | /** 14 | * @param {TreeNode} t1 15 | * @param {TreeNode} t2 16 | * @return {TreeNode} 17 | */ 18 | var mergeTrees = function(t1, t2) { 19 | if (!t2) return t1; 20 | if (!t1) return t2; 21 | t1.val += t2.val; 22 | t1.left = mergeTrees(t1.left, t2.left); 23 | t1.right = mergeTrees(t1.right, t2.right); 24 | return t1; 25 | }; 26 | -------------------------------------------------------------------------------- /js/problems/1.two-sum/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = [number[], number]; 6 | type Output = [number, number]; 7 | 8 | const cases = makeTestCases([ 9 | // 10 | { 11 | input: [[2, 7, 11, 15], 9], 12 | output: [0, 1], 13 | }, 14 | { 15 | input: [[3, 2, 4], 6], 16 | output: [1, 2], 17 | }, 18 | { 19 | input: [[0, 4, 3, 0], 0], 20 | output: [0, 3], 21 | }, 22 | ]); 23 | 24 | // * ------------------------------------------------ 25 | 26 | import { twoSum } from './solution'; 27 | testRunner(cases, twoSum); 28 | -------------------------------------------------------------------------------- /js/problems/1.two-sum/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=1 lang=javascript 3 | * 4 | * [1] Two Sum 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * @param {number[]} nums 10 | * @param {number} target 11 | * @return {number[]} 12 | */ 13 | const twoSum = (nums: number[], target: number): number[] => { 14 | // * ['52 ms', '92.7 %', '35 MB', '28.1 %'] 15 | 16 | // * value index map 17 | const map: Record = {}; 18 | 19 | nums.forEach((e, i) => (map[e] = i)); 20 | 21 | let p1 = 0; 22 | let p2 = 0; 23 | 24 | for (; p1 < nums.length; p1++) { 25 | p2 = map[target - nums[p1]]; 26 | if (p2 !== undefined && p1 !== p2) break; 27 | } 28 | 29 | // * exactly one solution, so no error checking 30 | return [p1, p2]; 31 | }; 32 | // @lc code=end 33 | 34 | export { twoSum }; 35 | -------------------------------------------------------------------------------- /js/problems/101.symmetric-tree/do.test.ts: -------------------------------------------------------------------------------- 1 | import { TreeNode } from './../../structures/tree/tree-node'; 2 | import { arrayToTree } from './../../structures/tree/tree-to-array'; 3 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 4 | 5 | // * ------------------------------------------------ 6 | 7 | type Input = TreeNode | null; 8 | type Output = boolean; 9 | 10 | const a2t = arrayToTree; 11 | 12 | const cases = makeTestCasesOfSingleInput([ 13 | // 14 | { 15 | input: a2t([1, 2, 2, 3, 4, 4, 3]), 16 | output: true, 17 | }, 18 | { 19 | input: a2t([1, 2, 2, null, 3, null, 3]), 20 | output: false, 21 | }, 22 | 23 | { 24 | input: a2t([1]), 25 | output: true, 26 | }, 27 | { 28 | input: a2t([null]), 29 | output: true, 30 | }, 31 | 32 | { 33 | input: a2t([1, 2, 3]), 34 | output: false, 35 | }, 36 | { 37 | input: a2t([1, 2, 2, 2, null, 2]), 38 | output: false, 39 | }, 40 | ]); 41 | 42 | // * ------------------------------------------------ 43 | 44 | import { isSymmetric } from './solution'; 45 | testRunner(cases, isSymmetric); 46 | -------------------------------------------------------------------------------- /js/problems/101.symmetric-tree/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=101 lang=javascript 3 | * 4 | * [101] Symmetric Tree 5 | */ 6 | 7 | type MaybeTreeNode = TreeNode | null; 8 | 9 | type TreeNode = { 10 | val: number; 11 | left: MaybeTreeNode; 12 | right: MaybeTreeNode; 13 | }; 14 | 15 | // @lc code=start 16 | /** 17 | * Definition for a binary tree node. 18 | * function TreeNode(val) { 19 | * this.val = val; 20 | * this.left = this.right = null; 21 | * } 22 | */ 23 | /** 24 | * @param {TreeNode} root 25 | * @return {boolean} 26 | */ 27 | const isSymmetric = (root: MaybeTreeNode): boolean => { 28 | // * ['52 ms', '96.66 %', '35.8 MB', '30 %'] 29 | 30 | if (root === null) return true; 31 | return isMirror(root.left, root.right); 32 | }; 33 | 34 | const isMirror = (l: MaybeTreeNode, r: MaybeTreeNode): boolean => { 35 | if (l === null && r === null) return true; 36 | if (!(l !== null && r !== null)) return false; 37 | return l.val === r.val && isMirror(l.left, r.right) && isMirror(l.right, r.left); 38 | }; 39 | 40 | // @lc code=end 41 | 42 | export { isSymmetric }; 43 | -------------------------------------------------------------------------------- /js/problems/104.maximum-depth-of-binary-tree/do.test.ts: -------------------------------------------------------------------------------- 1 | import { TreeNode } from './../../structures/tree/tree-node'; 2 | import { arrayToTree } from './../../structures/tree/tree-to-array'; 3 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 4 | 5 | // * ------------------------------------------------ 6 | 7 | type Input = TreeNode | null; 8 | type Output = number; 9 | 10 | const a2t = arrayToTree; 11 | 12 | const cases = makeTestCasesOfSingleInput([ 13 | // 14 | { 15 | input: a2t([3, 9, 20, null, null, 15, 7]), 16 | output: 3, 17 | }, 18 | { 19 | input: a2t([]), 20 | output: 0, 21 | }, 22 | { 23 | input: a2t([1]), 24 | output: 1, 25 | }, 26 | ]); 27 | 28 | // * ------------------------------------------------ 29 | 30 | import { maxDepth } from './solution'; 31 | testRunner(cases, maxDepth); 32 | -------------------------------------------------------------------------------- /js/problems/104.maximum-depth-of-binary-tree/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=104 lang=javascript 3 | * 4 | * [104] Maximum Depth of Binary Tree 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * Definition for a binary tree node. 10 | * function TreeNode(val) { 11 | * this.val = val; 12 | * this.left = this.right = null; 13 | * } 14 | */ 15 | 16 | interface TreeNode { 17 | val: number; 18 | left: TreeNode | null; 19 | right: TreeNode | null; 20 | } 21 | 22 | /** 23 | * @param {TreeNode} root 24 | * @return {number} 25 | */ 26 | const maxDepth = (root: TreeNode | null): number => { 27 | // * ['56 ms', '93.09 %', '37.2 MB', '28.13 %'] 28 | 29 | if (root === null) return 0; 30 | return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1; 31 | }; 32 | // @lc code=end 33 | 34 | export { maxDepth }; 35 | -------------------------------------------------------------------------------- /js/problems/112.path-sum/do.test.ts: -------------------------------------------------------------------------------- 1 | import { TreeNode } from './../../structures/tree/tree-node'; 2 | import { arrayToTree } from './../../structures/tree/tree-to-array'; 3 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 4 | 5 | // * ------------------------------------------------ 6 | 7 | type Input = [TreeNode | null, number]; 8 | type Output = boolean; 9 | 10 | const a2t = arrayToTree; 11 | 12 | // 5 13 | // / \ 14 | // 4 8 15 | // / / \ 16 | // 11 13 4 17 | // / \ \ 18 | // 7 2 1 19 | 20 | const tree = a2t([5, 4, 8, 11, null, 13, 4, 7, 2, null, null, null, null, null, 1]); 21 | 22 | const cases = makeTestCases([ 23 | // 24 | 25 | { 26 | input: [tree, 22], 27 | output: true, 28 | }, 29 | { 30 | input: [tree, 26], 31 | output: true, 32 | }, 33 | { 34 | input: [tree, 28], 35 | output: false, 36 | }, 37 | { 38 | input: [a2t([]), 0], 39 | output: false, 40 | }, 41 | { 42 | input: [a2t([1]), 1], 43 | output: true, 44 | }, 45 | { 46 | input: [a2t([0]), 1], 47 | output: false, 48 | }, 49 | ]); 50 | 51 | // * ------------------------------------------------ 52 | 53 | import { hasPathSum } from './solution'; 54 | testRunner(cases, hasPathSum); 55 | -------------------------------------------------------------------------------- /js/problems/112.path-sum/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=112 lang=javascript 3 | * 4 | * [112] Path Sum 5 | */ 6 | 7 | // @lc code=start 8 | 9 | type TreeNode = { 10 | val: number; 11 | left: MaybeTreeNode; 12 | right: MaybeTreeNode; 13 | }; 14 | 15 | type MaybeTreeNode = TreeNode | null; 16 | 17 | /** 18 | * Definition for a binary tree node. 19 | * function TreeNode(val, left, right) { 20 | * this.val = (val===undefined ? 0 : val) 21 | * this.left = (left===undefined ? null : left) 22 | * this.right = (right===undefined ? null : right) 23 | * } 24 | */ 25 | /** 26 | * @param {TreeNode} root 27 | * @param {number} sum 28 | * @return {boolean} 29 | */ 30 | const hasPathSum = (root: MaybeTreeNode, sum: number): boolean => { 31 | // * ['60 ms', '95.32 %', '37.3 MB', '49.22 %'] 32 | 33 | if (root === null) return false; 34 | 35 | const dfsSearch = (node: TreeNode, remain: number): boolean => { 36 | const { left: l, right: r, val: v } = node; 37 | 38 | remain -= v; 39 | 40 | if (l === null && r === null && remain === 0) return true; 41 | 42 | return (l !== null && dfsSearch(l, remain)) || (r !== null && dfsSearch(r, remain)); 43 | }; 44 | 45 | return dfsSearch(root, sum); 46 | }; 47 | // @lc code=end 48 | 49 | export { hasPathSum }; 50 | -------------------------------------------------------------------------------- /js/problems/113.path-sum-ii/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=113 lang=javascript 3 | * 4 | * [113] Path Sum II 5 | */ 6 | 7 | // @lc code=start 8 | 9 | type TreeNode = { 10 | val: number; 11 | left: MaybeTreeNode; 12 | right: MaybeTreeNode; 13 | }; 14 | 15 | type MaybeTreeNode = TreeNode | null; 16 | 17 | /** 18 | * Definition for a binary tree node. 19 | * function TreeNode(val, left, right) { 20 | * this.val = (val===undefined ? 0 : val) 21 | * this.left = (left===undefined ? null : left) 22 | * this.right = (right===undefined ? null : right) 23 | * } 24 | */ 25 | /** 26 | * @param {TreeNode} root 27 | * @param {number} sum 28 | * @return {number[][]} 29 | */ 30 | const pathSum = (root: MaybeTreeNode, sum: number): number[][] => { 31 | // * ['72 ms', '89.63 %', '38.1 MB', '54.62 %'] 32 | 33 | if (root === null) return []; 34 | 35 | const { left: L, val, right: R } = root; 36 | sum -= val; 37 | 38 | if (L === null && R === null && sum === 0) return [[val]]; 39 | 40 | const resLeft = pathSum(L, sum); 41 | const resRight = pathSum(R, sum); 42 | 43 | resLeft.forEach((res) => res.unshift(val)); 44 | resRight.forEach((res) => res.unshift(val)); 45 | 46 | return [...resLeft, ...resRight]; 47 | }; 48 | // @lc code=end 49 | 50 | export { pathSum }; 51 | -------------------------------------------------------------------------------- /js/problems/118.pascals-triangle/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = number; 6 | type Output = number[][]; 7 | 8 | const cases = makeTestCasesOfSingleInput([ 9 | // 10 | { 11 | input: 5, 12 | output: [ 13 | // 14 | [1], 15 | [1, 1], 16 | [1, 2, 1], 17 | [1, 3, 3, 1], 18 | [1, 4, 6, 4, 1], 19 | ], 20 | }, 21 | { 22 | input: 0, 23 | output: [], 24 | }, 25 | { 26 | input: 1, 27 | output: [[1]], 28 | }, 29 | ]); 30 | 31 | // * ------------------------------------------------ 32 | 33 | import { generate } from './solution'; 34 | testRunner(cases, generate); 35 | -------------------------------------------------------------------------------- /js/problems/118.pascals-triangle/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=118 lang=javascript 3 | * 4 | * [118] Pascal's Triangle 5 | */ 6 | /** 7 | * @param {number} numRows 8 | * @return {number[][]} 9 | */ 10 | const generate = (numRows: number): number[][] => { 11 | // * ['48 ms', '92.35 %', '33.7 MB', '100 %'] 12 | 13 | const result: number[][] = Array.from({ length: numRows }, () => []); 14 | 15 | for (let i = 0; i < numRows; i++) { 16 | const curRow = result[i]; 17 | curRow[0] = curRow[i] = 1; 18 | 19 | if (i < 2) continue; 20 | 21 | let prevRow = result[i - 1]; 22 | for (let j = 1; j < i; j++) { 23 | curRow[j] = prevRow[j] + prevRow[j - 1]; 24 | } 25 | } 26 | return result; 27 | }; 28 | 29 | export { generate }; 30 | -------------------------------------------------------------------------------- /js/problems/119.pascals-triangle-ii/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = number; 6 | type Output = number[]; 7 | 8 | const cases = makeTestCasesOfSingleInput([ 9 | // 10 | { 11 | input: 0, 12 | output: [1], 13 | }, 14 | { 15 | input: 1, 16 | output: [1, 1], 17 | }, 18 | { 19 | input: 2, 20 | output: [1, 2, 1], 21 | }, 22 | { 23 | input: 3, 24 | output: [1, 3, 3, 1], 25 | }, 26 | { 27 | input: 4, 28 | output: [1, 4, 6, 4, 1], 29 | }, 30 | ]); 31 | 32 | // * ------------------------------------------------ 33 | 34 | import { getRow } from './solution'; 35 | testRunner(cases, getRow); 36 | -------------------------------------------------------------------------------- /js/problems/119.pascals-triangle-ii/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=119 lang=javascript 3 | * 4 | * [119] Pascal's Triangle II 5 | */ 6 | /** 7 | * @param {number} rowIndex 8 | * @return {number[]} 9 | */ 10 | const getRow = (rowIndex: number): number[] => { 11 | // * ['44 ms', '98.06 %', '33.8 MB', '70 %'] 12 | 13 | // * O(k) space means in-place algo 14 | 15 | // * row `n` has `n+1` numbers 16 | // * row 0 is [1] 17 | // * row 1 is [1,1] 18 | // * row 1 is [1,2,1] 19 | 20 | const result = [1]; 21 | 22 | let row = 0; 23 | 24 | while (row < rowIndex) { 25 | row++; 26 | 27 | // * append last 1 28 | result[row] = 1; 29 | 30 | let prev = 1; 31 | let cur = null; 32 | 33 | // * loop adder 34 | for (let i = 1; i < row; i++) { 35 | cur = result[i]; 36 | result[i] += prev; 37 | prev = cur; 38 | } 39 | } 40 | 41 | return result; 42 | }; 43 | 44 | export { getRow }; 45 | -------------------------------------------------------------------------------- /js/problems/121.best-time-to-buy-and-sell-stock/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = number[]; 6 | type Output = number; 7 | 8 | const cases = makeTestCasesOfSingleInput([ 9 | // 10 | 11 | { input: [7], output: 0 }, 12 | { input: [7, 1, 5, 3, 6, 4], output: 5 }, 13 | { input: [7, 6, 4, 3, 1], output: 0 }, 14 | ]); 15 | 16 | // * ------------------------------------------------ 17 | 18 | import { maxProfit } from './solution'; 19 | testRunner(cases, maxProfit); 20 | -------------------------------------------------------------------------------- /js/problems/121.best-time-to-buy-and-sell-stock/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=121 lang=javascript 3 | * 4 | * [121] Best Time to Buy and Sell Stock 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * @param {number[]} prices 10 | * @return {number} 11 | */ 12 | const maxProfit = (prices: number[]): number => { 13 | // * ['56 ms', '86.44 %', '35.5 MB', '51.85 %'] 14 | 15 | // * O(n) solution, one pass 16 | 17 | let min = prices[0]; 18 | let profit = 0; 19 | 20 | for (let i = 1; i < prices.length; i++) { 21 | const cur = prices[i]; 22 | min = Math.min(min, cur); 23 | profit = Math.max(profit, cur - min); 24 | } 25 | 26 | return profit; 27 | }; 28 | // @lc code=end 29 | 30 | export { maxProfit }; 31 | -------------------------------------------------------------------------------- /js/problems/122.best-time-to-buy-and-sell-stock-ii/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = number[]; 6 | type Output = number; 7 | 8 | const cases = makeTestCasesOfSingleInput([ 9 | // 10 | 11 | { input: [7], output: 0 }, 12 | { input: [7, 1, 5, 3, 6, 4], output: 7 }, 13 | { input: [1, 2, 3, 4, 5], output: 4 }, 14 | { input: [7, 6, 4, 3, 1], output: 0 }, 15 | ]); 16 | 17 | // * ------------------------------------------------ 18 | 19 | import { maxProfit } from './solution'; 20 | testRunner(cases, maxProfit); 21 | -------------------------------------------------------------------------------- /js/problems/122.best-time-to-buy-and-sell-stock-ii/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=122 lang=javascript 3 | * 4 | * [122] Best Time to Buy and Sell Stock II 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * @param {number[]} prices 10 | * @return {number} 11 | */ 12 | const maxProfit = (prices: number[]): number => { 13 | // * ['52 ms', '93.42 %', '35.6 MB', '28.57 %'] 14 | 15 | if (prices.length < 2) return 0; 16 | 17 | let buy = prices[0]; 18 | let prev = buy; 19 | let sum = 0; 20 | 21 | for (let i = 1; i < prices.length; i++) { 22 | const cur = prices[i]; 23 | if (prev > cur) { 24 | sum += prev - buy; 25 | buy = cur; 26 | } 27 | prev = cur; 28 | } 29 | 30 | sum += prev - buy; 31 | 32 | return sum; 33 | }; 34 | // @lc code=end 35 | 36 | export { maxProfit }; 37 | -------------------------------------------------------------------------------- /js/problems/125.valid-palindrome/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = string; 6 | type Output = boolean; 7 | 8 | const cases = makeTestCasesOfSingleInput([ 9 | // 10 | 11 | { input: 'A man, a plan, a canal: Panama', output: true }, 12 | { input: 'race a car', output: false }, 13 | ]); 14 | 15 | // * ------------------------------------------------ 16 | 17 | import { isPalindrome } from './solution'; 18 | testRunner(cases, isPalindrome); 19 | 20 | import { isPalindrome as fancy } from './solution-fancy'; 21 | testRunner(cases, fancy, 'fancy'); 22 | -------------------------------------------------------------------------------- /js/problems/125.valid-palindrome/solution-fancy.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=125 lang=javascript 3 | * 4 | * [125] Valid Palindrome 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * @param {string} s 10 | * @return {boolean} 11 | */ 12 | const isPalindrome = (s: string): boolean => { 13 | // * ['64 ms', '91.3 %', '38.3 MB', '39.13 %'] 14 | 15 | const k = s.replace(/\W/g, '').toLowerCase(); 16 | 17 | return k.split('').reverse().join('') === k; 18 | }; 19 | // @lc code=end 20 | 21 | export { isPalindrome }; 22 | -------------------------------------------------------------------------------- /js/problems/125.valid-palindrome/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=125 lang=javascript 3 | * 4 | * [125] Valid Palindrome 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * @param {string} s 10 | * @return {boolean} 11 | */ 12 | const isPalindrome = (s: string): boolean => { 13 | // * ['60 ms', '96.8 %', '40.5 MB', '21.74 %'] 14 | 15 | let p1 = 0; 16 | let p2 = s.length - 1; 17 | while (p1 < p2) { 18 | while (/\W/.test(s[p1])) p1++; 19 | while (/\W/.test(s[p2])) p2--; 20 | 21 | if (s[p1] === s[p2] || s[p1].toLowerCase() === s[p2].toLowerCase()) { 22 | p1++; 23 | p2--; 24 | continue; 25 | } 26 | 27 | return false; 28 | } 29 | 30 | return true; 31 | }; 32 | // @lc code=end 33 | 34 | export { isPalindrome }; 35 | -------------------------------------------------------------------------------- /js/problems/133.clone-graph/do.test.ts: -------------------------------------------------------------------------------- 1 | import { arrayToGraph } from './../../structures/graph/graph-to-array'; 2 | import { GraphNode } from '../../structures/graph/graph-node'; 3 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 4 | 5 | // * ------------------------------------------------ 6 | 7 | type Input = GraphNode | null; 8 | type Output = GraphNode | null; 9 | 10 | const a2g = arrayToGraph; 11 | 12 | const cases = makeTestCasesOfSingleInput([ 13 | // 14 | { 15 | input: a2g([ 16 | [2, 4], 17 | [1, 3], 18 | [2, 4], 19 | [1, 3], 20 | ]), 21 | output: a2g([ 22 | [2, 4], 23 | [1, 3], 24 | [2, 4], 25 | [1, 3], 26 | ]), 27 | }, 28 | { 29 | input: a2g([[]]), 30 | output: a2g([[]]), 31 | }, 32 | { 33 | input: a2g([]), 34 | output: a2g([]), 35 | }, 36 | ]); 37 | 38 | // * ------------------------------------------------ 39 | 40 | import { cloneGraph } from './solution'; 41 | testRunner(cases, cloneGraph); 42 | 43 | import { Node } from './solution'; 44 | test('`new Node()` will success', () => { 45 | expect(new Node()).toBeInstanceOf(Node); 46 | }); 47 | -------------------------------------------------------------------------------- /js/problems/136.single-number/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = number[]; 6 | type Output = number; 7 | 8 | const cases = makeTestCasesOfSingleInput([ 9 | // 10 | 11 | { input: [2, 2, 1], output: 1 }, 12 | { input: [4, 1, 2, 1, 2], output: 4 }, 13 | ]); 14 | 15 | // * ------------------------------------------------ 16 | 17 | import { singleNumber } from './solution'; 18 | testRunner(cases, singleNumber); 19 | -------------------------------------------------------------------------------- /js/problems/136.single-number/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=136 lang=javascript 3 | * 4 | * [136] Single Number 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * @param {number[]} nums 10 | * @return {number} 11 | */ 12 | const singleNumber = (nums: number[]): number => { 13 | // * ['56 ms', '83.18 %', '35.3 MB', '88.46 %'] 14 | 15 | let result = 0; 16 | 17 | for (let i = 0; i < nums.length; i++) { 18 | result ^= nums[i]; 19 | } 20 | 21 | return result; 22 | }; 23 | // @lc code=end 24 | 25 | export { singleNumber }; 26 | -------------------------------------------------------------------------------- /js/problems/14.longest-common-prefix/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = string[]; 6 | type Output = string; 7 | 8 | const cases = makeTestCasesOfSingleInput([ 9 | // 10 | { 11 | input: ['flower', 'flow', 'flight'], 12 | output: 'fl', 13 | }, 14 | { 15 | input: ['dog', 'racecar', 'car'], 16 | output: '', 17 | }, 18 | { 19 | input: ['abc', 'abc', 'abc'], 20 | output: 'abc', 21 | }, 22 | { 23 | input: ['abc', 'abca', 'abc'], 24 | output: 'abc', 25 | }, 26 | { 27 | input: [''], 28 | output: '', 29 | }, 30 | { 31 | input: [], 32 | output: '', 33 | }, 34 | ]); 35 | 36 | // * ------------------------------------------------ 37 | 38 | import { longestCommonPrefix } from './solution'; 39 | testRunner(cases, longestCommonPrefix); 40 | -------------------------------------------------------------------------------- /js/problems/14.longest-common-prefix/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=14 lang=javascript 3 | * 4 | * [14] Longest Common Prefix 5 | */ 6 | /** 7 | * @param {string[]} strs 8 | * @return {string} 9 | */ 10 | const longestCommonPrefix = (strs: string[]): string => { 11 | if (strs.length < 1) return ''; 12 | if (strs.length === 1) return strs[0]; 13 | 14 | const strCount = strs.length; 15 | const s1 = strs[0]; 16 | 17 | for (let i = 0; i < s1.length; i++) { 18 | const e = s1[i]; 19 | for (let j = 1; j < strCount; j++) { 20 | if (strs[j][i] !== e) return s1.slice(0, i); 21 | } 22 | } 23 | 24 | return s1; 25 | }; 26 | 27 | export { longestCommonPrefix }; 28 | -------------------------------------------------------------------------------- /js/problems/141.linked-list-cycle/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=141 lang=javascript 3 | * 4 | * [141] Linked List Cycle 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * Definition for singly-linked list. 10 | * function ListNode(val) { 11 | * this.val = val; 12 | * this.next = null; 13 | * } 14 | */ 15 | 16 | interface ListNode { 17 | val: number; 18 | next: ListNode | null; 19 | } 20 | 21 | /** 22 | * @param {ListNode} head 23 | * @return {boolean} 24 | */ 25 | const hasCycle = (head: ListNode | null): boolean => { 26 | // * ['60 ms', '93.12 %', '36.3 MB', '100 %'] 27 | 28 | if (head === null) return false; 29 | 30 | let slow = head; 31 | let fast = head; 32 | 33 | do { 34 | if (fast.next === null || fast.next.next === null) return false; 35 | 36 | slow = slow!.next!; 37 | fast = fast.next.next; 38 | } while (slow !== fast); 39 | 40 | return true; 41 | }; 42 | // @lc code=end 43 | 44 | export { hasCycle }; 45 | -------------------------------------------------------------------------------- /js/problems/142.linked-list-cycle-ii/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=142 lang=javascript 3 | * 4 | * [142] Linked List Cycle II 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * Definition for singly-linked list. 10 | * function ListNode(val) { 11 | * this.val = val; 12 | * this.next = null; 13 | * } 14 | */ 15 | 16 | interface ListNode { 17 | val: number; 18 | next: ListNode | null; 19 | } 20 | 21 | /** 22 | * @param {ListNode} head 23 | * @return {ListNode} 24 | */ 25 | const detectCycle = (head: ListNode | null): ListNode | null => { 26 | // * ['60 ms', '95.65 %', '36.5 MB', '56.25 %'] 27 | // * https://leetcode-cn.com/problems/linked-list-cycle-ii/solution/huan-xing-lian-biao-ii-by-leetcode/113097/ 28 | 29 | if (head === null) return null; 30 | 31 | let slow = head; 32 | let fast = head; 33 | 34 | do { 35 | if (fast.next === null || fast.next.next === null) return null; 36 | 37 | slow = slow!.next!; 38 | fast = fast!.next!.next; 39 | } while (slow !== fast); 40 | 41 | slow = head; 42 | 43 | while (slow !== fast) { 44 | slow = slow!.next!; 45 | fast = fast!.next!; 46 | } 47 | 48 | return fast; 49 | }; 50 | // @lc code=end 51 | 52 | export { detectCycle }; 53 | -------------------------------------------------------------------------------- /js/problems/150.evaluate-reverse-polish-notation/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = string[]; 6 | type Output = number; 7 | 8 | const cases = makeTestCasesOfSingleInput([ 9 | // 10 | { 11 | input: ['2', '1', '+', '3', '*'], 12 | output: 9, 13 | }, 14 | { 15 | input: ['4', '13', '5', '/', '+'], 16 | output: 6, 17 | }, 18 | { 19 | input: ['10', '6', '9', '3', '+', '-11', '*', '/', '*', '17', '+', '5', '+'], 20 | output: 22, 21 | }, 22 | { 23 | input: ['10', '6', '-'], 24 | output: 4, 25 | }, 26 | ]); 27 | 28 | // * ------------------------------------------------ 29 | 30 | import { evalRPN } from './solution'; 31 | testRunner(cases, evalRPN); 32 | -------------------------------------------------------------------------------- /js/problems/150.evaluate-reverse-polish-notation/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=150 lang=javascript 3 | * 4 | * [150] Evaluate Reverse Polish Notation 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * @param {string[]} tokens 10 | * @return {number} 11 | */ 12 | const evalRPN = (tokens: string[]): number => { 13 | // * ['64 ms', '74.06 %', '36.4 MB', '100 %'] 14 | const resultStack: (number | string)[] = []; 15 | 16 | const math: Record number> = { 17 | '+': (a, b) => a + b, 18 | '-': (a, b) => a - b, 19 | '*': (a, b) => a * b, 20 | '/': (a, b) => ~~(a / b), 21 | }; 22 | 23 | for (let i = 0; i < tokens.length; i++) { 24 | const c = tokens[i]; 25 | const op = math[c]; 26 | if (op!) { 27 | const b = resultStack.pop() as number; 28 | const a = resultStack.pop() as number; 29 | resultStack.push(op(a, b)); 30 | } else { 31 | resultStack.push(Number(c)); 32 | } 33 | } 34 | 35 | return resultStack[0] as number; 36 | }; 37 | // @lc code=end 38 | 39 | export { evalRPN }; 40 | -------------------------------------------------------------------------------- /js/problems/151.reverse-words-in-a-string/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = string; 6 | type Output = string; 7 | 8 | const cases = makeTestCasesOfSingleInput([ 9 | // 10 | { 11 | input: 'the sky is blue', 12 | output: 'blue is sky the', 13 | }, 14 | { 15 | input: ' hello world! ', 16 | output: 'world! hello', 17 | }, 18 | { 19 | input: 'a good example', 20 | output: 'example good a', 21 | }, 22 | ]); 23 | 24 | // * ------------------------------------------------ 25 | 26 | import { reverseWords } from './solution'; 27 | testRunner(cases, reverseWords); 28 | -------------------------------------------------------------------------------- /js/problems/151.reverse-words-in-a-string/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=151 lang=javascript 3 | * 4 | * [151] Reverse Words in a String 5 | */ 6 | /** 7 | * @param {string} s 8 | * @return {string} 9 | */ 10 | const reverseWords = (s: string): string => { 11 | // * super easy js way 12 | // TODO try another method later // Seognil LC 2020/03/01 13 | 14 | return ( 15 | s 16 | .split(' ') 17 | 18 | // * remove useless spaces 19 | .filter((e) => e) 20 | .reverse() 21 | .join(' ') 22 | ); 23 | }; 24 | 25 | export { reverseWords }; 26 | -------------------------------------------------------------------------------- /js/problems/153.find-minimum-in-rotated-sorted-array/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = number[]; 6 | type Output = number; 7 | 8 | const cases = makeTestCasesOfSingleInput([ 9 | // 10 | { input: [3, 4, 5, 1, 2], output: 1 }, 11 | { input: [4, 5, 6, 7, 0, 1, 2], output: 0 }, 12 | 13 | { input: [3, 4, 5, 6, 7, 8, 9], output: 3 }, 14 | { input: [3, 4, 5, 6, 7, 8, 9, 0], output: 0 }, 15 | 16 | { input: [0, 1, 2, 3], output: 0 }, 17 | { input: [4, 0, 1, 2, 3], output: 0 }, 18 | { input: [4, 5, 0, 1, 2, 3], output: 0 }, 19 | { input: [4, 5, 6, 0, 1, 2, 3], output: 0 }, 20 | { input: [4, 5, 6, 7, 0, 1, 2, 3], output: 0 }, 21 | { input: [4, 5, 6, 7, 8, 0, 1, 2, 3], output: 0 }, 22 | { input: [4, 5, 6, 7, 8, 9, 0, 1, 2, 3], output: 0 }, 23 | 24 | { input: [1], output: 1 }, 25 | { input: [1, 2], output: 1 }, 26 | { input: [2, 1], output: 1 }, 27 | { input: [1, 2, 3], output: 1 }, 28 | { input: [3, 1, 2], output: 1 }, 29 | { input: [2, 3, 1], output: 1 }, 30 | ]); 31 | 32 | // * ------------------------------------------------ 33 | 34 | import { findMin } from './solution'; 35 | testRunner(cases, findMin); 36 | -------------------------------------------------------------------------------- /js/problems/153.find-minimum-in-rotated-sorted-array/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=153 lang=javascript 3 | * 4 | * [153] Find Minimum in Rotated Sorted Array 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * @param {number[]} nums 10 | * @return {number} 11 | */ 12 | const findMin = (nums: number[]): number => { 13 | // * ['48 ms', '94.33 %', '33.8 MB', '87.5 %'] 14 | 15 | let l = 0; 16 | let r = nums.length - 1; 17 | 18 | while (l < r) { 19 | const mid = ~~((l + r) / 2); 20 | 21 | if (nums[mid - 1] > nums[mid]) return nums[mid]; 22 | 23 | if (nums[mid] < nums[r]) { 24 | r = mid - 1; 25 | } else { 26 | l = mid + 1; 27 | } 28 | } 29 | 30 | return nums[l]; 31 | }; 32 | // @lc code=end 33 | 34 | export { findMin }; 35 | -------------------------------------------------------------------------------- /js/problems/154.find-minimum-in-rotated-sorted-array-ii/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=154 lang=javascript 3 | * 4 | * [154] Find Minimum in Rotated Sorted Array II 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * @param {number[]} nums 10 | * @return {number} 11 | */ 12 | const findMin = (nums: number[]): number => { 13 | // * ['52 ms', '89.47 %', '33.8 MB', '100 %'] 14 | let left = 0; 15 | let right = nums.length - 1; 16 | 17 | while (left < right) { 18 | // * if almost every val equals, then linear is faster than binary 19 | // * e.g: 2222212222322222222222220222, check that b**ch! 20 | 21 | while (nums[left] === nums[left + 1]) left += 1; 22 | while (nums[right] === nums[right - 1]) right -= 1; 23 | 24 | const mid = ~~((left + right) / 2); 25 | 26 | if (nums[mid - 1] > nums[mid]) return nums[mid]; 27 | 28 | if (nums[mid] < nums[right]) { 29 | right = mid - 1; 30 | } else { 31 | left = mid + 1; 32 | } 33 | } 34 | 35 | return nums[left]; 36 | }; 37 | // @lc code=end 38 | 39 | export { findMin }; 40 | -------------------------------------------------------------------------------- /js/problems/155.min-stack/do.test.ts: -------------------------------------------------------------------------------- 1 | import { MinStackClass, MinStackConstructor } from './types.d'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | const testRunnerRaw = (MinStack: MinStackConstructor) => { 6 | const minStack = new MinStack(); 7 | 8 | minStack.push(-2); 9 | minStack.push(0); 10 | minStack.push(-3); 11 | expect(minStack.getMin()).toEqual(-3); 12 | minStack.pop(); 13 | expect(minStack.top()).toEqual(0); 14 | expect(minStack.getMin()).toEqual(-2); 15 | }; 16 | 17 | // * ------------------------------------------------ 18 | 19 | import { MinStack as MinStackFn } from './solution'; 20 | import { MinStack } from './solution-class'; 21 | 22 | test('MinStack function version', () => { 23 | // @ts-ignore 24 | testRunnerRaw(MinStackFn as MinStackConstructor); 25 | }); 26 | 27 | test('MinStack class version', () => { 28 | testRunnerRaw(MinStack); 29 | }); 30 | -------------------------------------------------------------------------------- /js/problems/155.min-stack/solution-class.ts: -------------------------------------------------------------------------------- 1 | import { MinStackClass } from './types.d'; 2 | /* 3 | * @lc app=leetcode id=155 lang=javascript 4 | * 5 | * [155] Min Stack 6 | */ 7 | 8 | // @lc code=start 9 | /** 10 | * initialize your data structure here. 11 | */ 12 | class MinStack implements MinStackClass { 13 | private stack: number[]; 14 | private minStack: number[]; 15 | 16 | constructor() { 17 | this.stack = []; 18 | this.minStack = [Infinity]; 19 | } 20 | 21 | push(x: number): void { 22 | this.stack.push(x); 23 | this.minStack.push(Math.min(x, this.getMin())); 24 | } 25 | pop(): void { 26 | this.stack.pop(); 27 | this.minStack.pop(); 28 | } 29 | top(): number { 30 | return this.stack[this.stack.length - 1]; 31 | } 32 | getMin(): number { 33 | return this.minStack[this.minStack.length - 1]; 34 | } 35 | } 36 | 37 | /** 38 | * Your MinStack object will be instantiated and called as such: 39 | * var obj = new MinStack() 40 | * obj.push(x) 41 | * obj.pop() 42 | * var param_3 = obj.top() 43 | * var param_4 = obj.getMin() 44 | */ 45 | // @lc code=end 46 | 47 | export { MinStack }; 48 | -------------------------------------------------------------------------------- /js/problems/155.min-stack/types.d.ts: -------------------------------------------------------------------------------- 1 | export interface MinStackConstructor { 2 | new (): MinStackClass; 3 | } 4 | export interface MinStackClass { 5 | push(x: number): void; 6 | pop(): void; 7 | top(): number; 8 | getMin(): number; 9 | } 10 | -------------------------------------------------------------------------------- /js/problems/160.intersection-of-two-linked-lists/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=160 lang=javascript 3 | * 4 | * [160] Intersection of Two Linked Lists 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * Definition for singly-linked list. 10 | * function ListNode(val) { 11 | * this.val = val; 12 | * this.next = null; 13 | * } 14 | */ 15 | 16 | interface ListNode { 17 | val: number; 18 | next: MaybeList; 19 | } 20 | 21 | type MaybeList = ListNode | null; 22 | 23 | /** 24 | * @param {ListNode} headA 25 | * @param {ListNode} headB 26 | * @return {ListNode} 27 | */ 28 | const getIntersectionNode = (headA: MaybeList, headB: MaybeList): MaybeList => { 29 | // * ['80 ms', '89.7 %', '42.6 MB', '100 %'] 30 | 31 | if (headA === null || headB === null) return null; 32 | 33 | let p1: MaybeList = headA; 34 | let p2: MaybeList = headB; 35 | 36 | while (p1 !== p2) { 37 | p1 = p1 === null ? headB : p1.next; 38 | p2 = p2 === null ? headA : p2.next; 39 | } 40 | 41 | return p1; 42 | }; 43 | // @lc code=end 44 | 45 | export { getIntersectionNode }; 46 | -------------------------------------------------------------------------------- /js/problems/162.find-peak-element/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = number[]; 6 | type Output = number; 7 | 8 | // * check binary search only 9 | 10 | const cases = makeTestCasesOfSingleInput([ 11 | // 12 | { 13 | input: [1, 2, 3, 1], 14 | output: 2, 15 | }, 16 | { 17 | input: [1, 2, 1, 3, 5, 6, 4], 18 | output: 5, 19 | }, 20 | 21 | { 22 | input: [1, 2, 1], 23 | output: 1, 24 | }, 25 | { 26 | input: [1, 2, 3, 4], 27 | output: 3, 28 | }, 29 | { 30 | input: [4, 3, 2, 1], 31 | output: 0, 32 | }, 33 | ]); 34 | 35 | // * ------------------------------------------------ 36 | 37 | import { findPeakElement } from './solution'; 38 | testRunner(cases, findPeakElement); 39 | -------------------------------------------------------------------------------- /js/problems/162.find-peak-element/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=162 lang=javascript 3 | * 4 | * [162] Find Peak Element 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * @param {number[]} nums 10 | * @return {number} 11 | */ 12 | const findPeakElement = (nums: number[]): number => { 13 | // * ['48 ms', '92.04 %', '34.1 MB', '75 %'] 14 | 15 | let left = 0; 16 | let right = nums.length - 1; 17 | let mid = 0; 18 | 19 | nums[-1] = nums[nums.length] = -Infinity; 20 | 21 | while (true) { 22 | mid = ~~((left + right) / 2); 23 | 24 | if (nums[mid - 1] < nums[mid] && nums[mid] > nums[mid + 1]) break; 25 | 26 | if (nums[mid] < nums[mid + 1]) { 27 | left = mid + 1; 28 | } else { 29 | right = mid - 1; 30 | } 31 | } 32 | 33 | delete nums[-1]; 34 | delete nums[nums.length - 1]; 35 | 36 | return mid; 37 | }; 38 | // @lc code=end 39 | 40 | export { findPeakElement }; 41 | -------------------------------------------------------------------------------- /js/problems/167.two-sum-ii-input-array-is-sorted/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = [number[], number]; 6 | type Output = [number, number]; 7 | 8 | const cases = makeTestCases([ 9 | // 10 | { 11 | input: [[2, 7, 11, 15], 9], 12 | output: [1, 2], 13 | }, 14 | { 15 | input: [[2, 7, 11, 15], 13], 16 | output: [1, 3], 17 | }, 18 | { 19 | input: [[2, 7, 11, 15], 17], 20 | output: [1, 4], 21 | }, 22 | { 23 | input: [[2, 7, 11, 15], 18], 24 | output: [2, 3], 25 | }, 26 | { 27 | input: [[2, 7, 11, 15], 22], 28 | output: [2, 4], 29 | }, 30 | { 31 | input: [[2, 7, 11, 15], 26], 32 | output: [3, 4], 33 | }, 34 | 35 | { 36 | input: [[-20000, -10000, 1, 2, 3, 4, 20, 21, 96, 97, 98, 99, 10000, 20000], 41], 37 | output: [7, 8], 38 | }, 39 | ]); 40 | 41 | // * ------------------------------------------------ 42 | 43 | import { twoSum } from './solution'; 44 | testRunner(cases, twoSum); 45 | -------------------------------------------------------------------------------- /js/problems/167.two-sum-ii-input-array-is-sorted/readme.md: -------------------------------------------------------------------------------- 1 | What if duplicates? 2 | Whit if negative number? 3 | 4 | binary search is overkill, so I did not implement that 5 | -------------------------------------------------------------------------------- /js/problems/167.two-sum-ii-input-array-is-sorted/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=167 lang=javascript 3 | * 4 | * [167] Two Sum II - Input array is sorted 5 | */ 6 | /** 7 | * @param {number[]} numbers 8 | * @param {number} target 9 | * @return {number[]} 10 | */ 11 | const twoSum = (numbers: number[], target: number): number[] => { 12 | let left = 0; 13 | let right = numbers.length - 1; 14 | 15 | while (left < right) { 16 | const sum = numbers[left] + numbers[right]; 17 | if (sum === target) break; 18 | if (sum > target) right--; 19 | if (sum < target) left++; 20 | } 21 | 22 | return [left + 1, right + 1]; 23 | }; 24 | 25 | export { twoSum }; 26 | 27 | // 28 | -------------------------------------------------------------------------------- /js/problems/189.rotate-array/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = [number[], number]; 6 | type Output = number[]; 7 | 8 | const cases = makeTestCases([ 9 | // 10 | { 11 | input: [[1, 2, 3, 4, 5, 6, 7], 3], 12 | output: [5, 6, 7, 1, 2, 3, 4], 13 | }, 14 | { 15 | input: [[-1, -100, 3, 99], 2], 16 | output: [3, 99, -1, -100], 17 | }, 18 | { 19 | input: [[1, 2, 3, 4], 6], 20 | output: [3, 4, 1, 2], 21 | }, 22 | { 23 | input: [[1, 2, 3, 4], 0], 24 | output: [1, 2, 3, 4], 25 | }, 26 | { 27 | input: [[1], 6], 28 | output: [1], 29 | }, 30 | { 31 | input: [[], 6], 32 | output: [], 33 | }, 34 | ]); 35 | 36 | // * ------------------------------------------------ 37 | 38 | import { rotate as fn1 } from './solution'; 39 | import { rotate as fn2 } from './solution-map'; 40 | import { rotate as fn3 } from './solution-pointer'; 41 | testRunner(cases, fn1, 'popUnshift'); 42 | testRunner(cases, fn2, 'mapWriteBack'); 43 | testRunner(cases, fn3, 'pointer'); 44 | -------------------------------------------------------------------------------- /js/problems/189.rotate-array/solution-map.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=189 lang=javascript 3 | * 4 | * [189] Rotate Array 5 | */ 6 | /** 7 | * @param {number[]} nums 8 | * @param {number} k 9 | * @return {void} Do not return anything, modify nums in-place instead. 10 | */ 11 | const rotate = (nums: number[], k: number): void => { 12 | const l = nums.length; 13 | 14 | k = k % l; 15 | 16 | if (k !== 0) { 17 | // * O(n) space 18 | const mirror = nums.map((e, i) => nums[(l + i - k) % l]); 19 | 20 | // * write back 21 | for (let i = 0; i < l; i++) { 22 | nums[i] = mirror[i]; 23 | } 24 | } 25 | 26 | return; 27 | }; 28 | 29 | export { rotate }; 30 | -------------------------------------------------------------------------------- /js/problems/189.rotate-array/solution-pointer.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=189 lang=javascript 3 | * 4 | * [189] Rotate Array 5 | */ 6 | /** 7 | * @param {number[]} nums 8 | * @param {number} k 9 | * @return {void} Do not return anything, modify nums in-place instead. 10 | */ 11 | const rotate = (nums: number[], k: number): void => { 12 | const len = nums.length; 13 | 14 | k = k % len; 15 | 16 | if (len < 2 && k == 0) return; 17 | 18 | let writeCount = 0; 19 | let subLoopStartIndex = 0; 20 | 21 | while (writeCount < len) { 22 | let p = subLoopStartIndex; 23 | let cacheItem = nums[p]; 24 | 25 | do { 26 | const nextIndex = (p + k) % len; 27 | 28 | // * jump, write, cache 29 | const temp = nums[nextIndex]; 30 | nums[nextIndex] = cacheItem; 31 | cacheItem = temp; 32 | p = nextIndex; 33 | 34 | writeCount++; 35 | } while (subLoopStartIndex !== p); 36 | 37 | subLoopStartIndex++; 38 | } 39 | 40 | return; 41 | }; 42 | 43 | export { rotate }; 44 | -------------------------------------------------------------------------------- /js/problems/189.rotate-array/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=189 lang=javascript 3 | * 4 | * [189] Rotate Array 5 | */ 6 | /** 7 | * @param {number[]} nums 8 | * @param {number} k 9 | * @return {void} Do not return anything, modify nums in-place instead. 10 | */ 11 | const rotate = (nums: number[], k: number): void => { 12 | if (nums.length < 2) return; 13 | 14 | k = k % nums.length; 15 | 16 | // * unshift is costly, maybe O(kn) space? 17 | while (k-- > 0) nums.unshift(nums.pop()!); 18 | 19 | return; 20 | }; 21 | 22 | export { rotate }; 23 | -------------------------------------------------------------------------------- /js/problems/19.remove-nth-node-from-end-of-list/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=19 lang=javascript 3 | * 4 | * [19] Remove Nth Node From End of List 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * Definition for singly-linked list. 10 | * function ListNode(val) { 11 | * this.val = val; 12 | * this.next = null; 13 | * } 14 | */ 15 | 16 | type MaybeList = ListNode | null; 17 | 18 | interface ListNode { 19 | val: number; 20 | next: MaybeList; 21 | } 22 | 23 | /** 24 | * @param {ListNode} head 25 | * @param {number} n 26 | * @return {ListNode} 27 | */ 28 | const removeNthFromEnd = (head: MaybeList, n: number): MaybeList => { 29 | // * ['48 ms', '98.59 %', '34.1 MB', '68.18 %'] 30 | 31 | if (head === null) return head; 32 | 33 | const dummy = { next: head } as ListNode; 34 | 35 | let ahead: MaybeList = dummy; 36 | let behind: MaybeList = dummy; 37 | 38 | let count = 0; 39 | while (count < n) { 40 | ahead = ahead.next!; 41 | count++; 42 | } 43 | 44 | while (ahead.next) { 45 | ahead = ahead.next; 46 | behind = behind.next!; 47 | } 48 | 49 | behind.next = behind.next!.next; 50 | 51 | return dummy.next; 52 | }; 53 | // @lc code=end 54 | 55 | export { removeNthFromEnd }; 56 | -------------------------------------------------------------------------------- /js/problems/2.add-two-numbers/do.test.ts: -------------------------------------------------------------------------------- 1 | import { arrayToList } from '../../structures/linked-list/list-to-array'; 2 | import { ListNode } from '../../structures/linked-list/list-node'; 3 | 4 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 5 | 6 | // * ------------------------------------------------ 7 | 8 | type MaybeList = ListNode | null; 9 | 10 | type Input = [MaybeList, MaybeList]; 11 | type Output = MaybeList; 12 | 13 | const a2l = arrayToList; 14 | 15 | const cases = makeTestCases([ 16 | // 17 | { 18 | input: [a2l([2, 4, 3]), a2l([5, 6, 4])], 19 | output: a2l([7, 0, 8]), 20 | }, 21 | { 22 | input: [a2l([1, 2, 3, 4]), a2l([2])], 23 | output: a2l([3, 2, 3, 4]), 24 | }, 25 | { 26 | input: [a2l([2]), a2l([1, 2, 3, 4])], 27 | output: a2l([3, 2, 3, 4]), 28 | }, 29 | { 30 | input: [a2l([1, 2, 4]), a2l([1, 2, 6])], 31 | output: a2l([2, 4, 0, 1]), 32 | }, 33 | ]); 34 | 35 | // * ------------------------------------------------ 36 | 37 | import { addTwoNumbers } from './solution'; 38 | testRunner(cases, addTwoNumbers); 39 | -------------------------------------------------------------------------------- /js/problems/2.add-two-numbers/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=2 lang=javascript 3 | * 4 | * [2] Add Two Numbers 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * Definition for singly-linked list. 10 | * function ListNode(val) { 11 | * this.val = val; 12 | * this.next = null; 13 | * } 14 | */ 15 | 16 | type MaybeList = ListNode | null; 17 | 18 | class ListNode { 19 | public next: MaybeList = null; 20 | constructor(public val: number = 0) {} 21 | } 22 | 23 | /** 24 | * @param {ListNode} l1 25 | * @param {ListNode} l2 26 | * @return {ListNode} 27 | */ 28 | const addTwoNumbers = (l1: MaybeList, l2: MaybeList): MaybeList => { 29 | // * ['108 ms', '88.84 %', '38.5 MB', '44.44 %'] 30 | 31 | const dummy = new ListNode(); 32 | let cur = dummy; 33 | let carry = 0; 34 | 35 | while (l1 || l2) { 36 | const val1 = l1 !== null ? l1.val : 0; 37 | const val2 = l2 !== null ? l2.val : 0; 38 | const sum = val1 + val2 + carry; 39 | cur = cur.next = new ListNode(sum % 10); 40 | carry = sum >= 10 ? 1 : 0; 41 | if (l1) l1 = l1.next; 42 | if (l2) l2 = l2.next; 43 | } 44 | 45 | if (carry) cur.next = new ListNode(1); 46 | 47 | return dummy.next; 48 | }; 49 | // @lc code=end 50 | 51 | export { addTwoNumbers }; 52 | -------------------------------------------------------------------------------- /js/problems/20.valid-parentheses/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = string; 6 | type Output = boolean; 7 | 8 | const cases = makeTestCasesOfSingleInput([ 9 | // 10 | { 11 | input: '()', 12 | output: true, 13 | }, 14 | { 15 | input: '()[]{}', 16 | output: true, 17 | }, 18 | { 19 | input: '(]', 20 | output: false, 21 | }, 22 | { 23 | input: '([)]', 24 | output: false, 25 | }, 26 | { 27 | input: '{[]}', 28 | output: true, 29 | }, 30 | { 31 | input: '{[[](())]{{}()[(){}]}}', 32 | output: true, 33 | }, 34 | { 35 | input: '{[[](())]{}()[(){}]}}', 36 | output: false, 37 | }, 38 | ]); 39 | 40 | // * ------------------------------------------------ 41 | 42 | import { isValid } from './solution'; 43 | testRunner(cases, isValid); 44 | -------------------------------------------------------------------------------- /js/problems/20.valid-parentheses/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=20 lang=javascript 3 | * 4 | * [20] Valid Parentheses 5 | */ 6 | /** 7 | * @param {string} s 8 | * @return {boolean} 9 | */ 10 | const isValid = (s: string): boolean => { 11 | const stack = []; 12 | 13 | const match: Record = { 14 | ')': '(', 15 | ']': '[', 16 | '}': '{', 17 | }; 18 | 19 | for (let i = 0; i < s.length; i++) { 20 | const e = s[i]; 21 | if (match[e]) { 22 | // * fast failed 23 | if (stack.pop() != match[e]) return false; 24 | } else { 25 | stack.push(e); 26 | } 27 | } 28 | 29 | return stack.length === 0; 30 | }; 31 | 32 | export { isValid }; 33 | -------------------------------------------------------------------------------- /js/problems/200.number-of-islands/solution.ts: -------------------------------------------------------------------------------- 1 | import { Grid } from './types'; 2 | 3 | /* 4 | * @lc app=leetcode id=200 lang=javascript 5 | * 6 | * [200] Number of Islands 7 | */ 8 | 9 | // @lc code=start 10 | /** 11 | * @param {character[][]} grid 12 | * @return {number} 13 | */ 14 | const numIslands = (grid: Grid): number => { 15 | // * DFS ['60 ms', '90.61 %', '37.5 MB', '74.19 %'] 16 | // * https://leetcode.com/problems/number-of-islands/discuss/391717/JavaScript-DFS-56ms-very-easy-to-understand 17 | 18 | if (!grid.length) return 0; 19 | 20 | const row = grid.length; 21 | const col = grid[0].length; 22 | 23 | const dfsWipeout = (r: number, c: number): void => { 24 | if (r < 0 || r >= row || c < 0 || c >= col) return; 25 | if (grid[r][c] === '0') return; 26 | 27 | // * wipe island part 28 | grid[r][c] = '0'; 29 | 30 | dfsWipeout(r + 1, c); 31 | dfsWipeout(r - 1, c); 32 | dfsWipeout(r, c + 1); 33 | dfsWipeout(r, c - 1); 34 | }; 35 | 36 | let count = 0; 37 | for (let i = 0; i < row; i++) { 38 | for (let j = 0; j < col; j++) { 39 | if (grid[i][j] === '1') { 40 | count++; 41 | dfsWipeout(i, j); 42 | } 43 | } 44 | } 45 | 46 | return count; 47 | }; 48 | // @lc code=end 49 | 50 | export { numIslands }; 51 | -------------------------------------------------------------------------------- /js/problems/200.number-of-islands/types.d.ts: -------------------------------------------------------------------------------- 1 | export type Grid = ('1' | '0')[][]; 2 | -------------------------------------------------------------------------------- /js/problems/203.remove-linked-list-elements/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=203 lang=javascript 3 | * 4 | * [203] Remove Linked List Elements 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * Definition for singly-linked list. 10 | * function ListNode(val) { 11 | * this.val = val; 12 | * this.next = null; 13 | * } 14 | */ 15 | 16 | type MaybeList = ListNode | null; 17 | 18 | interface ListNode { 19 | val: number; 20 | next: MaybeList; 21 | } 22 | 23 | /** 24 | * @param {ListNode} head 25 | * @param {number} val 26 | * @return {ListNode} 27 | */ 28 | const removeElements = (head: MaybeList, val: number): MaybeList => { 29 | // * ['60 ms', '99.36 %', '36.9 MB', '62.5 %'] 30 | 31 | if (head === null) return head; 32 | 33 | const dummy = { next: head } as ListNode; 34 | 35 | let cur: MaybeList = dummy; 36 | 37 | while (cur.next) { 38 | if (cur!.next.val === val) { 39 | cur.next = cur.next.next; 40 | continue; 41 | } 42 | 43 | cur = cur.next; 44 | } 45 | 46 | return dummy.next; 47 | }; 48 | // @lc code=end 49 | 50 | export { removeElements }; 51 | -------------------------------------------------------------------------------- /js/problems/206.reverse-linked-list/do.test.ts: -------------------------------------------------------------------------------- 1 | import { ListNode } from '../../structures/linked-list/list-node'; 2 | import { arrayToList } from '../../structures/linked-list/list-to-array'; 3 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 4 | 5 | // * ------------------------------------------------ 6 | 7 | type Input = ListNode | null; 8 | type Output = ListNode | null; 9 | 10 | const a2l = arrayToList; 11 | 12 | const cases = makeTestCasesOfSingleInput([ 13 | // 14 | { 15 | input: a2l([1, 2, 3, 4, 5]), 16 | output: a2l([5, 4, 3, 2, 1]), 17 | }, 18 | { 19 | input: a2l([]), 20 | output: a2l([]), 21 | }, 22 | ]); 23 | 24 | // * ------------------------------------------------ 25 | 26 | import { reverseList } from './solution'; 27 | testRunner(cases, reverseList); 28 | -------------------------------------------------------------------------------- /js/problems/206.reverse-linked-list/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=206 lang=javascript 3 | * 4 | * [206] Reverse Linked List 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * Definition for singly-linked list. 10 | * function ListNode(val) { 11 | * this.val = val; 12 | * this.next = null; 13 | * } 14 | */ 15 | 16 | interface ListNode { 17 | val: number; 18 | next: ListNode | null; 19 | } 20 | 21 | /** 22 | * @param {ListNode} head 23 | * @return {ListNode} 24 | */ 25 | const reverseList = (head: ListNode | null): ListNode | null => { 26 | // * ['48 ms', '98.66 %', '34.9 MB', '73.91 %'] 27 | 28 | // * null cur -> next -> ... 29 | // * prev cur next 30 | // * prev <- cur next 31 | // * prev cur next 32 | 33 | let cur = head; 34 | let prev: ListNode | null = null; 35 | let next: ListNode | null; 36 | 37 | while (cur !== null) { 38 | next = cur.next; 39 | cur.next = prev; 40 | prev = cur; 41 | cur = next; 42 | } 43 | 44 | return prev; 45 | }; 46 | // @lc code=end 47 | 48 | export { reverseList }; 49 | -------------------------------------------------------------------------------- /js/problems/209.minimum-size-subarray-sum/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = [number, number[]]; 6 | type Output = number; 7 | 8 | const cases = makeTestCases([ 9 | // 10 | { 11 | input: [7, [2, 3, 1, 2, 4, 3]], 12 | output: 2, 13 | }, 14 | { 15 | input: [99, [2, 3, 1, 2, 4, 3]], 16 | output: 0, 17 | }, 18 | { 19 | input: [99, []], 20 | output: 0, 21 | }, 22 | { 23 | input: [99, [1, 2, 99, 3]], 24 | output: 1, 25 | }, 26 | ]); 27 | 28 | // * ------------------------------------------------ 29 | 30 | import { minSubArrayLen } from './solution'; 31 | testRunner(cases, minSubArrayLen); 32 | -------------------------------------------------------------------------------- /js/problems/209.minimum-size-subarray-sum/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=209 lang=javascript 3 | * 4 | * [209] Minimum Size Subarray Sum 5 | */ 6 | /** 7 | * @param {number} s 8 | * @param {number[]} nums 9 | * @return {number} 10 | */ 11 | const minSubArrayLen = (s: number, nums: number[]): number => { 12 | if (!nums.length) return 0; 13 | 14 | const len = nums.length; 15 | 16 | let p1 = 0, 17 | p2 = -1, 18 | minLen = Infinity, 19 | sum = 0; 20 | 21 | while (p2 < len) { 22 | while (sum < s) { 23 | p2++; 24 | sum += nums[p2]; 25 | } 26 | 27 | while (sum >= s) { 28 | minLen = Math.min(minLen, p2 - p1 + 1); 29 | 30 | if (minLen === 1) return 1; 31 | 32 | sum -= nums[p1]; 33 | p1++; 34 | } 35 | } 36 | 37 | return minLen === Infinity ? 0 : minLen; 38 | }; 39 | 40 | export { minSubArrayLen }; 41 | -------------------------------------------------------------------------------- /js/problems/21.merge-two-sorted-lists/do.test.ts: -------------------------------------------------------------------------------- 1 | import { arrayToList } from '../../structures/linked-list/list-to-array'; 2 | import { ListNode } from '../../structures/linked-list/list-node'; 3 | 4 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 5 | 6 | // * ------------------------------------------------ 7 | 8 | type Input = [ListNode | null, ListNode | null]; 9 | type Output = ListNode | null; 10 | 11 | const a2l = arrayToList; 12 | 13 | const cases = makeTestCases([ 14 | // 15 | { 16 | input: [a2l([1, 2, 4]), a2l([1, 3, 4])], 17 | output: a2l([1, 1, 2, 3, 4, 4]), 18 | }, 19 | { 20 | input: [a2l([1, 2, 3, 7, 8, 9]), a2l([4, 5, 6])], 21 | output: a2l([1, 2, 3, 4, 5, 6, 7, 8, 9]), 22 | }, 23 | { 24 | input: [a2l([1, 2, 4]), a2l([])], 25 | output: a2l([1, 2, 4]), 26 | }, 27 | { 28 | input: [a2l([]), a2l([])], 29 | output: a2l([]), 30 | }, 31 | ]); 32 | 33 | // * ------------------------------------------------ 34 | 35 | import { mergeTwoLists } from './solution'; 36 | testRunner(cases, mergeTwoLists); 37 | -------------------------------------------------------------------------------- /js/problems/21.merge-two-sorted-lists/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=21 lang=javascript 3 | * 4 | * [21] Merge Two Sorted Lists 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * Definition for singly-linked list. 10 | * function ListNode(val) { 11 | * this.val = val; 12 | * this.next = null; 13 | * } 14 | */ 15 | 16 | interface ListNode { 17 | val: number; 18 | next: ListNode | null; 19 | } 20 | 21 | /** 22 | * @param {ListNode} l1 23 | * @param {ListNode} l2 24 | * @return {ListNode} 25 | */ 26 | const mergeTwoLists = (l1: ListNode | null, l2: ListNode | null): ListNode => { 27 | // * ['60 ms', '86.75 %', '35.5 MB', '79.49 %'] 28 | 29 | const head: ListNode = { val: 0, next: null }; 30 | 31 | let cur = head; 32 | 33 | while (l1 && l2) { 34 | if (l1.val < l2.val) { 35 | cur.next = l1; 36 | l1 = l1.next; 37 | } else { 38 | cur.next = l2; 39 | l2 = l2.next; 40 | } 41 | 42 | cur = cur.next; 43 | } 44 | 45 | // * one list clear, one list remaining 46 | cur.next = l1 || l2; 47 | 48 | return head.next!; 49 | }; 50 | // @lc code=end 51 | 52 | export { mergeTwoLists }; 53 | -------------------------------------------------------------------------------- /js/problems/217.contains-duplicate/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = number[]; 6 | type Output = boolean; 7 | 8 | const cases = makeTestCasesOfSingleInput([ 9 | // 10 | 11 | { input: [1, 2, 3, 1], output: true }, 12 | { input: [1, 2, 3, 4], output: false }, 13 | { input: [1, 1, 1, 3, 3, 4, 3, 2, 4, 2], output: true }, 14 | ]); 15 | 16 | // * ------------------------------------------------ 17 | 18 | import { containsDuplicate } from './solution'; 19 | testRunner(cases, containsDuplicate); 20 | -------------------------------------------------------------------------------- /js/problems/217.contains-duplicate/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=217 lang=javascript 3 | * 4 | * [217] Contains Duplicate 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * @param {number[]} nums 10 | * @return {boolean} 11 | */ 12 | const containsDuplicate = (nums: number[]): boolean => { 13 | // * ['56 ms', '97.28 %', '40 MB', '88.24 %'] 14 | 15 | return new Set(nums).size !== nums.length; 16 | }; 17 | // @lc code=end 18 | 19 | export { containsDuplicate }; 20 | -------------------------------------------------------------------------------- /js/problems/225.implement-stack-using-queues/do.test.ts: -------------------------------------------------------------------------------- 1 | import { MyStackClass, MyStackConstructor } from './types.d'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | const testRunnerRaw = (MyStack: MyStackConstructor) => { 6 | const stack = new MyStack(); 7 | 8 | stack.push(1); 9 | stack.push(2); 10 | expect(stack.top()).toEqual(2); 11 | expect(stack.pop()).toEqual(2); 12 | expect(stack.empty()).toEqual(false); 13 | 14 | expect(stack.pop()).toEqual(1); 15 | expect(stack.empty()).toEqual(true); 16 | }; 17 | 18 | // * ------------------------------------------------ 19 | 20 | import { MyStack as MyStackFn } from './solution'; 21 | import { MyStack } from './solution-class'; 22 | 23 | test('MyStack function version', () => { 24 | // @ts-ignore 25 | testRunnerRaw(MyStackFn as MyStackConstructor); 26 | }); 27 | 28 | test('MyStack class version', () => { 29 | testRunnerRaw(MyStack); 30 | }); 31 | -------------------------------------------------------------------------------- /js/problems/225.implement-stack-using-queues/solution-class.ts: -------------------------------------------------------------------------------- 1 | import { MyStackClass } from './types.d'; 2 | /* 3 | * @lc app=leetcode id=225 lang=javascript 4 | * 5 | * [225] Implement Stack using Queues 6 | */ 7 | 8 | // @lc code=start 9 | /** 10 | * Initialize your data structure here. 11 | */ 12 | class MyStack implements MyStackClass { 13 | // * ['48 ms', '90.81 %', '33.9 MB', '50 %'] 14 | 15 | private arr: number[] = []; 16 | 17 | push(x: number) { 18 | this.arr.push(x); 19 | } 20 | pop() { 21 | return this.arr.pop()!; 22 | } 23 | top() { 24 | return this.arr[this.arr.length - 1]; 25 | } 26 | empty() { 27 | return this.arr.length < 1; 28 | } 29 | } 30 | 31 | /** 32 | * Your MyStack object will be instantiated and called as such: 33 | * var obj = new MyStack() 34 | * obj.push(x) 35 | * var param_2 = obj.pop() 36 | * var param_3 = obj.top() 37 | * var param_4 = obj.empty() 38 | */ 39 | // @lc code=end 40 | 41 | export { MyStack }; 42 | -------------------------------------------------------------------------------- /js/problems/225.implement-stack-using-queues/types.d.ts: -------------------------------------------------------------------------------- 1 | export interface MyStackConstructor { 2 | new (): MyStackClass; 3 | } 4 | export interface MyStackClass { 5 | push(x: number): void; 6 | pop(): number; 7 | top(): number; 8 | empty(): boolean; 9 | } 10 | -------------------------------------------------------------------------------- /js/problems/232.implement-queue-using-stacks/do.test.ts: -------------------------------------------------------------------------------- 1 | import { MyQueueClass, MyQueueConstructor } from './types.d'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | const testRunnerRaw = (MyQueue: MyQueueConstructor) => { 6 | const queue = new MyQueue(); 7 | 8 | queue.push(1); 9 | queue.push(2); 10 | 11 | expect(queue.peek()).toEqual(1); 12 | expect(queue.pop()).toEqual(1); 13 | expect(queue.empty()).toEqual(false); 14 | 15 | expect(queue.pop()).toEqual(2); 16 | expect(queue.empty()).toEqual(true); 17 | }; 18 | 19 | // * ------------------------------------------------ 20 | 21 | import { MyQueue as MyQueueFn } from './solution'; 22 | import { MyQueue } from './solution-class'; 23 | 24 | test('MyQueue function version', () => { 25 | // @ts-ignore 26 | testRunnerRaw(MyQueueFn as MyQueueConstructor); 27 | }); 28 | 29 | test('MyQueue class version', () => { 30 | testRunnerRaw(MyQueue); 31 | }); 32 | -------------------------------------------------------------------------------- /js/problems/232.implement-queue-using-stacks/solution-class.ts: -------------------------------------------------------------------------------- 1 | import { MyQueueClass } from './types.d'; 2 | /* 3 | * @lc app=leetcode id=232 lang=javascript 4 | * 5 | * [232] Implement Queue using Stacks 6 | */ 7 | 8 | // @lc code=start 9 | /** 10 | * Initialize your data structure here. 11 | */ 12 | class MyQueue implements MyQueueClass { 13 | // * ['48 ms', '90.58 %', '33.6 MB', '100 %'] 14 | 15 | private arr: number[] = []; 16 | 17 | push(x: number) { 18 | this.arr.push(x); 19 | } 20 | pop() { 21 | return this.arr.shift()!; 22 | } 23 | peek() { 24 | return this.arr[0]; 25 | } 26 | empty() { 27 | return this.arr.length < 1; 28 | } 29 | } 30 | 31 | /** 32 | * Your MyQueue object will be instantiated and called as such: 33 | * var obj = new MyQueue() 34 | * obj.push(x) 35 | * var param_2 = obj.pop() 36 | * var param_3 = obj.peek() 37 | * var param_4 = obj.empty() 38 | */ 39 | // @lc code=end 40 | 41 | export { MyQueue }; 42 | -------------------------------------------------------------------------------- /js/problems/232.implement-queue-using-stacks/types.d.ts: -------------------------------------------------------------------------------- 1 | export interface MyQueueConstructor { 2 | new (): MyQueueClass; 3 | } 4 | export interface MyQueueClass { 5 | push(x: number): void; 6 | pop(): number; 7 | peek(): number; 8 | empty(): boolean; 9 | } 10 | -------------------------------------------------------------------------------- /js/problems/234.palindrome-linked-list/do.test.ts: -------------------------------------------------------------------------------- 1 | import { ListNode } from '../../structures/linked-list/list-node'; 2 | import { arrayToList } from '../../structures/linked-list/list-to-array'; 3 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 4 | 5 | // * ------------------------------------------------ 6 | 7 | type Input = ListNode | null; 8 | type Output = boolean; 9 | 10 | const a2l = arrayToList; 11 | 12 | const cases = makeTestCasesOfSingleInput([ 13 | // 14 | { 15 | input: a2l([1, 2]), 16 | output: false, 17 | }, 18 | { 19 | input: a2l([1, 2, 2, 1]), 20 | output: true, 21 | }, 22 | { 23 | input: a2l([1, 2, 3, 2, 1]), 24 | output: true, 25 | }, 26 | { 27 | input: a2l([1]), 28 | output: true, 29 | }, 30 | { 31 | input: a2l([]), 32 | output: true, 33 | }, 34 | ]); 35 | 36 | // * ------------------------------------------------ 37 | 38 | import { isPalindrome } from './solution'; 39 | testRunner(cases, isPalindrome); 40 | 41 | import { isPalindrome as unsafe } from './solution-unsafe'; 42 | testRunner(cases, unsafe, 'unsafe'); 43 | -------------------------------------------------------------------------------- /js/problems/237.delete-node-in-a-linked-list/do.test.ts: -------------------------------------------------------------------------------- 1 | import { arrayToList } from '../../structures/linked-list/list-to-array'; 2 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 3 | 4 | // * ------------------------------------------------ 5 | 6 | const a2l = arrayToList; 7 | 8 | type MaybeList = ListNode | null; 9 | 10 | interface ListNode { 11 | val: number; 12 | next: MaybeList; 13 | } 14 | 15 | type Solution = (node: ListNode) => void; 16 | 17 | const myTestRunner = (fn: Solution) => { 18 | test('case 1', () => { 19 | const list = a2l([4, 5, 1, 9]); 20 | const result = a2l([4, 1, 9]); 21 | const node = list!.next!; 22 | 23 | deleteNode(node); 24 | expect(list).toEqual(result); 25 | }); 26 | 27 | test('case 2', () => { 28 | const list = a2l([4, 5, 1, 9]); 29 | const result = a2l([4, 5, 9]); 30 | const node = list!.next!.next!; 31 | 32 | deleteNode(node); 33 | expect(list).toEqual(result); 34 | }); 35 | }; 36 | 37 | // * ------------------------------------------------ 38 | 39 | import { deleteNode } from './solution'; 40 | myTestRunner(deleteNode); 41 | -------------------------------------------------------------------------------- /js/problems/237.delete-node-in-a-linked-list/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=237 lang=javascript 3 | * 4 | * [237] Delete Node in a Linked List 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * Definition for singly-linked list. 10 | * function ListNode(val) { 11 | * this.val = val; 12 | * this.next = null; 13 | * } 14 | */ 15 | 16 | type MaybeList = ListNode | null; 17 | 18 | interface ListNode { 19 | val: number; 20 | next: MaybeList; 21 | } 22 | 23 | /** 24 | * @param {ListNode} node 25 | * @return {void} Do not return anything, modify node in-place instead. 26 | */ 27 | const deleteNode = (node: ListNode): void => { 28 | // * ['56 ms', '94.09 %', '35.6 MB', '58.33 %'] 29 | 30 | node.val = node.next!.val; 31 | node.next = node.next!.next; 32 | }; 33 | // @lc code=end 34 | 35 | export { deleteNode }; 36 | -------------------------------------------------------------------------------- /js/problems/24.swap-nodes-in-pairs/do.test.ts: -------------------------------------------------------------------------------- 1 | import { ListNode } from '../../structures/linked-list/list-node'; 2 | import { arrayToList } from '../../structures/linked-list/list-to-array'; 3 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 4 | 5 | // * ------------------------------------------------ 6 | 7 | type Input = ListNode | null; 8 | type Output = ListNode | null; 9 | 10 | const a2l = arrayToList; 11 | 12 | const cases = makeTestCasesOfSingleInput([ 13 | // 14 | { 15 | input: a2l([1, 2, 3, 4]), 16 | output: a2l([2, 1, 4, 3]), 17 | }, 18 | { 19 | input: a2l([1]), 20 | output: a2l([1]), 21 | }, 22 | { 23 | input: a2l([1, 2, 3]), 24 | output: a2l([2, 1, 3]), 25 | }, 26 | { 27 | input: a2l([]), 28 | output: a2l([]), 29 | }, 30 | ]); 31 | 32 | // * ------------------------------------------------ 33 | 34 | import { swapPairs } from './solution'; 35 | testRunner(cases, swapPairs); 36 | -------------------------------------------------------------------------------- /js/problems/24.swap-nodes-in-pairs/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=24 lang=javascript 3 | * 4 | * [24] Swap Nodes in Pairs 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * Definition for singly-linked list. 10 | * function ListNode(val) { 11 | * this.val = val; 12 | * this.next = null; 13 | * } 14 | */ 15 | 16 | interface ListNode { 17 | val: number; 18 | next: ListNode | null; 19 | } 20 | 21 | /** 22 | * @param {ListNode} head 23 | * @return {ListNode} 24 | */ 25 | const swapPairs = (head: ListNode | null): ListNode | null => { 26 | // * ['52 ms', '80.94 %', '33.7 MB', '89.47 %'] 27 | 28 | if (head === null) return null; 29 | 30 | const dummy = { next: head } as ListNode; 31 | 32 | let cur = dummy; 33 | 34 | while (cur.next && cur.next.next) { 35 | const n1 = cur.next!; 36 | const n2 = n1.next!; 37 | const n3 = n2.next; 38 | n1.next = n3; 39 | n2.next = n1; 40 | cur.next = n2; 41 | cur = n1; 42 | } 43 | 44 | return dummy.next; 45 | }; 46 | // @lc code=end 47 | 48 | export { swapPairs }; 49 | -------------------------------------------------------------------------------- /js/problems/242.valid-anagram/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = [string, string]; 6 | type Output = boolean; 7 | 8 | const cases = makeTestCases([ 9 | // 10 | 11 | { input: ['anagram', 'nagaram'], output: true }, 12 | { input: ['rat', 'car'], output: false }, 13 | { input: ['rat', 'ca'], output: false }, 14 | ]); 15 | 16 | // * ------------------------------------------------ 17 | 18 | import { isAnagram } from './solution'; 19 | testRunner(cases, isAnagram); 20 | 21 | import { isAnagram as fancy } from './solution-fancy'; 22 | testRunner(cases, fancy, 'fancy'); 23 | -------------------------------------------------------------------------------- /js/problems/242.valid-anagram/solution-fancy.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=242 lang=javascript 3 | * 4 | * [242] Valid Anagram 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * @param {string} s 10 | * @param {string} t 11 | * @return {boolean} 12 | */ 13 | const isAnagram = (s: string, t: string): boolean => { 14 | // * ['104 ms', '31.74 %', '40.2 MB', '8.16 %'] 15 | 16 | if (s.length === t.length) { 17 | return s.split('').sort().join() === t.split('').sort().join(); 18 | } else { 19 | return false; 20 | } 21 | }; 22 | // @lc code=end 23 | 24 | export { isAnagram }; 25 | -------------------------------------------------------------------------------- /js/problems/242.valid-anagram/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=242 lang=javascript 3 | * 4 | * [242] Valid Anagram 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * @param {string} s 10 | * @param {string} t 11 | * @return {boolean} 12 | */ 13 | const isAnagram = (s: string, t: string): boolean => { 14 | // * ['60 ms', '95.71 %', '35.8 MB', '93.88 %'] 15 | 16 | const countA = new Array(26).fill(0); 17 | const countB = new Array(26).fill(0); 18 | 19 | for (let i = 0; i < s.length; i++) { 20 | countA[s.charCodeAt(i) - 97] += 1; 21 | } 22 | for (let i = 0; i < t.length; i++) { 23 | countB[t.charCodeAt(i) - 97] += 1; 24 | } 25 | 26 | return countA.every((e, i) => countB[i] === e); 27 | }; 28 | // @lc code=end 29 | 30 | export { isAnagram }; 31 | -------------------------------------------------------------------------------- /js/problems/26.remove-duplicates-from-sorted-array/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = number[]; 6 | type Output = number; 7 | 8 | const cases = makeTestCasesOfSingleInput([ 9 | // 10 | { 11 | input: [1, 1, 2], 12 | output: 2, 13 | }, 14 | { 15 | input: [0, 0, 1, 1, 1, 2, 2, 3, 3, 4], 16 | output: 5, 17 | }, 18 | ]); 19 | 20 | // * ------------------------------------------------ 21 | 22 | import { removeDuplicates } from './solution'; 23 | testRunner(cases, removeDuplicates); 24 | -------------------------------------------------------------------------------- /js/problems/26.remove-duplicates-from-sorted-array/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=26 lang=javascript 3 | * 4 | * [26] Remove Duplicates from Sorted Array 5 | */ 6 | /** 7 | * @param {number[]} nums 8 | * @return {number} 9 | */ 10 | const removeDuplicates = (nums: number[]): number => { 11 | // * should modify in-place 12 | 13 | let newLen = 0; 14 | let prevNum; 15 | 16 | for (let i = 0; i < nums.length; i++) { 17 | const curNum = nums[i]; 18 | 19 | if (curNum === prevNum) continue; 20 | 21 | nums[newLen] = prevNum = curNum; 22 | 23 | newLen++; 24 | } 25 | 26 | // * cut off rest items by directly change length 27 | nums.length = newLen; 28 | 29 | // * return new length 30 | return newLen; 31 | }; 32 | 33 | export { removeDuplicates }; 34 | -------------------------------------------------------------------------------- /js/problems/27.remove-element/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = [number[], number]; 6 | type Output = number; 7 | 8 | const cases = makeTestCases([ 9 | // 10 | { 11 | input: [[3, 2, 2, 3], 3], 12 | output: 2, 13 | }, 14 | { 15 | input: [[0, 1, 2, 2, 3, 0, 4, 2], 2], 16 | output: 5, 17 | }, 18 | ]); 19 | 20 | // * ------------------------------------------------ 21 | 22 | import { removeElement } from './solution'; 23 | testRunner(cases, removeElement); 24 | -------------------------------------------------------------------------------- /js/problems/27.remove-element/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=27 lang=javascript 3 | * 4 | * [27] Remove Element 5 | */ 6 | /** 7 | * @param {number[]} nums 8 | * @param {number} val 9 | * @return {number} 10 | */ 11 | const removeElement = (nums: number[], val: number): number => { 12 | const len = nums.length; 13 | let p1 = 0; 14 | for (let p2 = 0; p2 < len; p2++) { 15 | if (nums[p2] != val) { 16 | nums[p1] = nums[p2]; 17 | p1++; 18 | } 19 | } 20 | return p1; 21 | }; 22 | 23 | export { removeElement }; 24 | -------------------------------------------------------------------------------- /js/problems/278.first-bad-version/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type IsBadVersion = (n: number) => boolean; 6 | type Checker = (n: number) => number; 7 | type Solution = (isBadVersion: IsBadVersion) => Checker; 8 | 9 | const rawTestRunner = (solution: Solution) => { 10 | const genTest = (firstBad: number) => { 11 | const isBadVersion: IsBadVersion = (n) => n >= firstBad; 12 | const versionCount = ~~(firstBad * (1 + Math.random())); 13 | 14 | test(`have ${versionCount} versions, ${firstBad} is first bad version`, () => { 15 | expect(solution(isBadVersion)(versionCount)).toEqual(firstBad); 16 | }); 17 | }; 18 | 19 | describe('First Bad Version', () => { 20 | genTest(1); 21 | genTest(2); 22 | genTest(30); 23 | genTest(200); 24 | genTest(87); 25 | genTest(13); 26 | }); 27 | }; 28 | 29 | // * ------------------------------------------------ 30 | 31 | import { solution } from './solution'; 32 | import { numIslands } from '../200.number-of-islands/solution'; 33 | rawTestRunner(solution); 34 | -------------------------------------------------------------------------------- /js/problems/278.first-bad-version/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=278 lang=javascript 3 | * 4 | * [278] First Bad Version 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * Definition for isBadVersion() 10 | * 11 | * @param {integer} version number 12 | * @return {boolean} whether the version is bad 13 | * isBadVersion = function(version) { 14 | * ... 15 | * }; 16 | */ 17 | 18 | type IsBadVersion = (n: number) => boolean; 19 | 20 | /** 21 | * @param {integer} n Total versions 22 | * @return {integer} The first bad version 23 | */ 24 | type Checker = (n: number) => number; 25 | 26 | type Solution = (isBadVersion: IsBadVersion) => Checker; 27 | 28 | /** 29 | * @param {function} isBadVersion() 30 | * @return {function} 31 | */ 32 | const solution: Solution = (isBadVersion) => (n) => { 33 | // * ['48 ms', '88.25 %', '33.7 MB', '76.92 %'] 34 | 35 | let left = 1; 36 | let right = n; 37 | 38 | while (left < right) { 39 | let mid = ~~((right + left) / 2); 40 | 41 | if (isBadVersion(mid)) { 42 | right = mid; 43 | } else { 44 | left = mid + 1; 45 | } 46 | } 47 | return right; 48 | }; 49 | 50 | // @lc code=end 51 | 52 | export { solution }; 53 | -------------------------------------------------------------------------------- /js/problems/279.perfect-squares/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = number; 6 | type Output = number; 7 | 8 | const cases = makeTestCasesOfSingleInput([ 9 | // 10 | { input: 12, output: 3 }, 11 | { input: 13, output: 2 }, 12 | { input: 7168, output: 4 }, 13 | 14 | { input: 1, output: 1 }, 15 | { input: 4, output: 1 }, 16 | { input: 9, output: 1 }, 17 | { input: 16, output: 1 }, 18 | ]); 19 | 20 | // * ------------------------------------------------ 21 | 22 | import { numSquares } from './solution'; 23 | import { numSquares as bfs } from './solution-bfs'; 24 | import { numSquares as bfs2 } from './solution-bfs-opts'; 25 | 26 | testRunner(cases, numSquares); 27 | testRunner(cases, bfs, 'bfs'); 28 | testRunner(cases, bfs2, 'bfsOpts'); 29 | -------------------------------------------------------------------------------- /js/problems/279.perfect-squares/solution-bfs.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=279 lang=javascript 3 | * 4 | * [279] Perfect Squares 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * @param {number} n 10 | * @return {number} 11 | */ 12 | const numSquares = (n: number): number => { 13 | // * bfs ? ['92 ms', '90.63 %', '41.5 MB', '12.5 %'] 14 | 15 | // * double memory usage, not good 16 | const queue: [number, number][] = [[n, 1]]; 17 | 18 | const visited: Record = {}; 19 | 20 | while (queue.length) { 21 | const [n, step] = queue.shift()!; 22 | const sqrtN = n ** 0.5; 23 | const intSqrtN = Math.floor(sqrtN); 24 | 25 | // * found 26 | if (sqrtN === intSqrtN) return step; 27 | 28 | const nextStep = step + 1; 29 | for (let i = intSqrtN; i > 0; i--) { 30 | const rest = n - i ** 2; 31 | if (!visited[rest]) { 32 | queue.push([rest, nextStep]); 33 | visited[rest] = true; 34 | } 35 | } 36 | } 37 | 38 | // * really never touched 39 | return 0; 40 | }; 41 | 42 | // @lc code=end 43 | 44 | export { numSquares }; 45 | -------------------------------------------------------------------------------- /js/problems/279.perfect-squares/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=279 lang=javascript 3 | * 4 | * [279] Perfect Squares 5 | */ 6 | 7 | const history: Record = {}; 8 | 9 | // @lc code=start 10 | /** 11 | * @param {number} n 12 | * @return {number} 13 | */ 14 | const numSquares = (n: number): number => { 15 | // * dp ['68 ms', '97.17 %', '35.8 MB', '100 %'] 16 | 17 | const sqrtN = n ** 0.5; 18 | const intSqrtN = Math.floor(sqrtN); 19 | 20 | // * for just square number 21 | if (sqrtN == intSqrtN) return 1; 22 | 23 | // * ---------------- rest cases 24 | 25 | let restMin: number = Infinity; 26 | 27 | for (let i = intSqrtN; i > 0; i--) { 28 | const rest = n - i ** 2; 29 | 30 | if (!history[rest]) history[rest] = numSquares(rest); 31 | 32 | restMin = Math.min(restMin, history[rest]); 33 | } 34 | 35 | // * for add-ups 36 | return restMin + 1; 37 | }; 38 | 39 | // @lc code=end 40 | 41 | export { numSquares }; 42 | -------------------------------------------------------------------------------- /js/problems/28.implement-str-str/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = [string, string]; 6 | type Output = number; 7 | 8 | const cases = makeTestCases([ 9 | // 10 | { 11 | input: ['hello', 'll'], 12 | output: 2, 13 | }, 14 | { 15 | input: ['aaaaa', 'bba'], 16 | output: -1, 17 | }, 18 | { 19 | input: ['abacababc', 'abab'], 20 | output: 4, 21 | }, 22 | { 23 | input: ['hello', ''], 24 | output: 0, 25 | }, 26 | ]); 27 | 28 | // * ------------------------------------------------ 29 | 30 | import { strStr } from './solution'; 31 | testRunner(cases, strStr); 32 | -------------------------------------------------------------------------------- /js/problems/28.implement-str-str/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=28 lang=javascript 3 | * 4 | * [28] Implement strStr() 5 | */ 6 | /** 7 | * @param {string} fullStr 8 | * @param {string} subStr 9 | * @return {number} 10 | */ 11 | const strStr = (fullStr: string, subStr: string): number => { 12 | // TODO it's simple loop, try kmp later // seognil LC 2019/06/08 13 | 14 | const fullLen = fullStr.length; 15 | const subLen = subStr.length; 16 | 17 | if (!subLen) return 0; 18 | 19 | for (let i = 0; i <= fullLen - subLen; i++) { 20 | let match = true; 21 | for (let j = 0; j < subLen && match; j++) { 22 | if (fullStr[i + j] != subStr[j]) match = false; 23 | } 24 | 25 | if (match) return i; 26 | } 27 | 28 | // * not found 29 | return -1; 30 | }; 31 | 32 | export { strStr }; 33 | -------------------------------------------------------------------------------- /js/problems/283.move-zeroes/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = number[]; 6 | type Output = number[]; 7 | 8 | const cases = makeTestCasesOfSingleInput([ 9 | // 10 | { 11 | input: [0, 1, 0, 3, 12], 12 | output: [1, 3, 12, 0, 0], 13 | }, 14 | { 15 | input: [], 16 | output: [], 17 | }, 18 | { 19 | input: [1], 20 | output: [1], 21 | }, 22 | { 23 | input: [0], 24 | output: [0], 25 | }, 26 | ]); 27 | 28 | // * ------------------------------------------------ 29 | 30 | import { moveZeroes } from './solution'; 31 | testRunner(cases, moveZeroes); 32 | -------------------------------------------------------------------------------- /js/problems/283.move-zeroes/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=283 lang=javascript 3 | * 4 | * [283] Move Zeroes 5 | */ 6 | /** 7 | * @param {number[]} nums 8 | * @return {void} Do not return anything, modify nums in-place instead. 9 | */ 10 | const moveZeroes = (nums: number[]): void => { 11 | const len = nums.length; 12 | 13 | let p1 = 0; 14 | let p2 = 0; 15 | 16 | // * walk two pointers 17 | while (p2 < len) { 18 | if (nums[p2] !== 0) { 19 | nums[p1] = nums[p2]; 20 | p1++; 21 | } 22 | 23 | p2++; 24 | } 25 | 26 | // * set reset to zero 27 | while (p1 < len) { 28 | nums[p1] = 0; 29 | p1++; 30 | } 31 | 32 | return; 33 | }; 34 | 35 | export { moveZeroes }; 36 | -------------------------------------------------------------------------------- /js/problems/287.find-the-duplicate-number/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = number[]; 6 | type Output = number; 7 | 8 | const cases = makeTestCasesOfSingleInput([ 9 | // 10 | { input: [1, 3, 4, 2, 2], output: 2 }, 11 | { input: [3, 1, 3, 4, 2], output: 3 }, 12 | ]); 13 | 14 | // * ------------------------------------------------ 15 | 16 | import { findDuplicate } from './solution'; 17 | testRunner(cases, findDuplicate); 18 | -------------------------------------------------------------------------------- /js/problems/287.find-the-duplicate-number/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=287 lang=javascript 3 | * 4 | * [287] Find the Duplicate Number 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * @param {number[]} nums 10 | * @return {number} 11 | */ 12 | const findDuplicate = (nums: number[]): number => { 13 | // * ['56 ms', '80.02 %', '35.3 MB', '85.71 %'] 14 | 15 | // * https://leetcode-cn.com/problems/find-the-duplicate-number/solution/er-fen-fa-si-lu-ji-dai-ma-python-by-liweiwei1419/ 16 | 17 | // * search log(n) times, every time costs n steps 18 | // * and it's O(1) extra space 19 | 20 | let left = 1; 21 | let right = nums.length - 1; 22 | 23 | while (left < right) { 24 | const mid = ~~((left + right) / 2); 25 | 26 | let count = 0; 27 | nums.forEach((e) => { 28 | if (e <= mid) { 29 | count++; 30 | } 31 | }); 32 | 33 | if (count <= mid) { 34 | left = mid + 1; 35 | } else { 36 | right = mid; 37 | } 38 | } 39 | 40 | return left; 41 | }; 42 | // @lc code=end 43 | 44 | export { findDuplicate }; 45 | -------------------------------------------------------------------------------- /js/problems/31.next-permutation/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = number[]; 6 | type Output = number[]; 7 | 8 | const cases = makeTestCasesOfSingleInput([ 9 | // 10 | { 11 | input: [1, 2, 3], 12 | output: [1, 3, 2], 13 | }, 14 | { 15 | input: [3, 2, 1], 16 | output: [1, 2, 3], 17 | }, 18 | { 19 | input: [1, 1, 5], 20 | output: [1, 5, 1], 21 | }, 22 | { 23 | input: [1, 7, 2, 3, 4], 24 | output: [1, 7, 2, 4, 3], 25 | }, 26 | { 27 | input: [2, 7, 5, 3], 28 | output: [3, 2, 5, 7], 29 | }, 30 | { 31 | input: [4, 7, 5, 3], 32 | output: [5, 3, 4, 7], 33 | }, 34 | ]); 35 | 36 | // * ------------------------------------------------ 37 | 38 | import { nextPermutation } from './solution'; 39 | testRunner(cases, nextPermutation); 40 | -------------------------------------------------------------------------------- /js/problems/31.next-permutation/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=31 lang=javascript 3 | * 4 | * [31] Next Permutation 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * @param {number[]} nums 10 | * @return {void} Do not return anything, modify nums in-place instead. 11 | */ 12 | const nextPermutation = (nums: number[]): void => { 13 | // * ['60 ms', '96.52 %', '35 MB', '41.43 %'] 14 | 15 | const len = nums.length; 16 | 17 | for (let i = len - 2; i >= 0; i--) { 18 | const k = nums[i]; 19 | if (k >= nums[i + 1]) continue; 20 | 21 | // * found, make next permutation 22 | reverse(nums, i + 1, len - 1); 23 | for (let j = i + 1; j < len; j++) { 24 | if (k < nums[j]) { 25 | swap(nums, i, j); 26 | 27 | // * found 28 | return; 29 | } 30 | } 31 | } 32 | 33 | // * not found, so it's highest, make lowsest 34 | reverse(nums, 0, len - 1); 35 | }; 36 | 37 | const swap = (nums: number[], i: number, j: number): void => { 38 | const t = nums[i]; 39 | nums[i] = nums[j]; 40 | nums[j] = t; 41 | }; 42 | 43 | const reverse = (nums: number[], i: number, j: number): void => { 44 | while (i < j) swap(nums, i, j), i++, j--; 45 | }; 46 | 47 | // @lc code=end 48 | 49 | export { nextPermutation }; 50 | -------------------------------------------------------------------------------- /js/problems/328.odd-even-linked-list/do.test.ts: -------------------------------------------------------------------------------- 1 | import { ListNode } from '../../structures/linked-list/list-node'; 2 | import { arrayToList } from '../../structures/linked-list/list-to-array'; 3 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 4 | 5 | // * ------------------------------------------------ 6 | 7 | type Input = ListNode | null; 8 | type Output = ListNode | null; 9 | 10 | const a2l = arrayToList; 11 | 12 | const cases = makeTestCasesOfSingleInput([ 13 | // 14 | { 15 | input: a2l([1, 2, 3, 4, 5]), 16 | output: a2l([1, 3, 5, 2, 4]), 17 | }, 18 | { 19 | input: a2l([2, 1, 3, 5, 6, 4, 7]), 20 | output: a2l([2, 3, 6, 7, 1, 5, 4]), 21 | }, 22 | { 23 | input: a2l([1]), 24 | output: a2l([1]), 25 | }, 26 | { 27 | input: a2l([1, 2]), 28 | output: a2l([1, 2]), 29 | }, 30 | { 31 | input: a2l([]), 32 | output: a2l([]), 33 | }, 34 | ]); 35 | 36 | // * ------------------------------------------------ 37 | 38 | import { oddEvenList } from './solution'; 39 | testRunner(cases, oddEvenList); 40 | -------------------------------------------------------------------------------- /js/problems/328.odd-even-linked-list/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=328 lang=javascript 3 | * 4 | * [328] Odd Even Linked List 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * Definition for singly-linked list. 10 | * function ListNode(val) { 11 | * this.val = val; 12 | * this.next = null; 13 | * } 14 | */ 15 | 16 | type MaybeList = ListNode | null; 17 | 18 | interface ListNode { 19 | val: number; 20 | next: MaybeList; 21 | } 22 | 23 | /** 24 | * @param {ListNode} head 25 | * @return {ListNode} 26 | */ 27 | const oddEvenList = (head: MaybeList): MaybeList => { 28 | // * ['64 ms', '83.74 %', '36.2 MB', '100 %'] 29 | 30 | if (head === null) return head; 31 | 32 | const dummy = { next: null } as ListNode; 33 | 34 | let p1: ListNode = head; 35 | let p2: MaybeList = dummy; 36 | 37 | while (p1.next !== null && p1.next.next !== null) { 38 | p2 = p2.next = p1.next; 39 | p1 = p1.next = p1.next!.next; 40 | } 41 | 42 | if (p1.next !== null) p2 = p2.next = p1.next; 43 | 44 | p2.next = null; 45 | p1.next = dummy.next; 46 | 47 | return head; 48 | }; 49 | // @lc code=end 50 | 51 | export { oddEvenList }; 52 | -------------------------------------------------------------------------------- /js/problems/33.search-in-rotated-sorted-array/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = [number[], number]; 6 | type Output = number; 7 | 8 | const cases = makeTestCases([ 9 | // 10 | { 11 | input: [[4, 5, 6, 7, 0, 1, 2], 0], 12 | output: 4, 13 | }, 14 | { 15 | input: [[4, 5, 6, 7, 0, 1, 2], 3], 16 | output: -1, 17 | }, 18 | 19 | { 20 | input: [[3, 4, 5, 6, 7, 8, 9, 0, 1, 2], 5], 21 | output: 2, 22 | }, 23 | { 24 | input: [[3, 4, 5, 6, 7, 8, 9, 0, 1, 2], 1], 25 | output: 8, 26 | }, 27 | { 28 | input: [[7, 8, 9, 0, 1, 2, 3, 4, 5, 6], 8], 29 | output: 1, 30 | }, 31 | { 32 | input: [[7, 8, 9, 0, 1, 2, 3, 4, 5, 6], 5], 33 | output: 8, 34 | }, 35 | ]); 36 | 37 | // * ------------------------------------------------ 38 | 39 | import { search } from './solution'; 40 | testRunner(cases, search); 41 | -------------------------------------------------------------------------------- /js/problems/33.search-in-rotated-sorted-array/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=33 lang=javascript 3 | * 4 | * [33] Search in Rotated Sorted Array 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * @param {number[]} nums 10 | * @param {number} target 11 | * @return {number} 12 | */ 13 | const search = (nums: number[], target: number): number => { 14 | // * ['52 ms', '88.13 %', '33 MB', '100 %'] 15 | 16 | let l = 0; 17 | let r = nums.length - 1; 18 | 19 | while (l <= r) { 20 | const mid = ~~((l + r) / 2); 21 | const valLeft = nums[l]; 22 | const valRight = nums[r]; 23 | const valMid = nums[mid]; 24 | 25 | if (valMid === target) return mid; 26 | 27 | if (valMid < valRight) { 28 | if (valMid < target && target <= valRight) { 29 | l = mid + 1; 30 | } else { 31 | r = mid - 1; 32 | } 33 | } else { 34 | if (valLeft <= target && target < valMid) { 35 | r = mid - 1; 36 | } else { 37 | l = mid + 1; 38 | } 39 | } 40 | } 41 | 42 | return -1; 43 | }; 44 | 45 | // @lc code=end 46 | 47 | export { search }; 48 | -------------------------------------------------------------------------------- /js/problems/331.verify-preorder-serialization-of-a-binary-tree/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = string; 6 | type Output = boolean; 7 | 8 | const cases = makeTestCasesOfSingleInput([ 9 | // 10 | { 11 | input: '9,3,4,#,#,1,#,#,2,#,6,#,#', 12 | output: true, 13 | }, 14 | { 15 | input: '1,#', 16 | output: false, 17 | }, 18 | { 19 | input: '9,#,#,1', 20 | output: false, 21 | }, 22 | 23 | { 24 | input: '9,#,1,#,#', 25 | output: true, 26 | }, 27 | { 28 | input: '9,#,#,#,1', 29 | output: false, 30 | }, 31 | 32 | { 33 | input: '#', 34 | output: true, 35 | }, 36 | ]); 37 | 38 | // * ------------------------------------------------ 39 | 40 | import { isValidSerialization } from './solution'; 41 | testRunner(cases, isValidSerialization); 42 | 43 | import { isValidSerialization as wipe } from './solution-wipe'; 44 | testRunner(cases, wipe, 'wipe'); 45 | -------------------------------------------------------------------------------- /js/problems/331.verify-preorder-serialization-of-a-binary-tree/solution-wipe.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=331 lang=javascript 3 | * 4 | * [331] Verify Preorder Serialization of a Binary Tree 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * @param {string} preorder 10 | * @return {boolean} 11 | */ 12 | const isValidSerialization = (preorder: string): boolean => { 13 | // * ['52 ms', '88.06 %', '35.1 MB', '100 %'] 14 | 15 | let str = preorder; 16 | 17 | while (/\d+,#,#/.test(str)) { 18 | str = str.replace(/\d+,#,#/g, '#'); 19 | } 20 | 21 | return str === '#'; 22 | }; 23 | // @lc code=end 24 | 25 | export { isValidSerialization }; 26 | -------------------------------------------------------------------------------- /js/problems/331.verify-preorder-serialization-of-a-binary-tree/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=331 lang=javascript 3 | * 4 | * [331] Verify Preorder Serialization of a Binary Tree 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * @param {string} preorder 10 | * @return {boolean} 11 | */ 12 | const isValidSerialization = (preorder: string): boolean => { 13 | // * ['48 ms', '94.03 %', '34.9 MB', '100 %'] 14 | 15 | // * https://leetcode-cn.com/problems/verify-preorder-serialization-of-a-binary-tree/solution/yan-zheng-er-cha-shu-de-qian-xu-xu-lie-hua-by-leet/ 16 | 17 | let slot = 1; 18 | let prev = ''; 19 | 20 | for (let i = 0; i < preorder.length; i++) { 21 | const e = preorder[i]; 22 | 23 | if (e === ',') slot += prev === '#' ? -1 : 1; 24 | 25 | if (slot <= 0) return false; 26 | 27 | prev = e; 28 | } 29 | 30 | slot += prev === '#' ? -1 : 1; 31 | 32 | return slot === 0; 33 | }; 34 | // @lc code=end 35 | 36 | export { isValidSerialization }; 37 | -------------------------------------------------------------------------------- /js/problems/34.find-first-and-last-position-of-element-in-sorted-array/solution-semi-bs.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=34 lang=javascript 3 | * 4 | * [34] Find First and Last Position of Element in Sorted Array 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * @param {number[]} nums 10 | * @param {number} target 11 | * @return {number[]} 12 | */ 13 | const searchRange = (nums: number[], target: number): number[] => { 14 | // * ['56 ms', '67.46 %', '35.2 MB', '30 %'] 15 | 16 | // * binary search + linear search, so bit slower in long range 17 | 18 | let left = 0; 19 | let right = nums.length - 1; 20 | 21 | while (left <= right) { 22 | let pivot = ~~((left + right) / 2); 23 | 24 | if (nums[pivot] < target) { 25 | left = pivot + 1; 26 | } else if (nums[pivot] > target) { 27 | right = pivot - 1; 28 | } else { 29 | var midCache; 30 | midCache = left = right = pivot; 31 | 32 | while (nums[--pivot] == target) left = pivot; 33 | 34 | pivot = midCache; 35 | 36 | while (nums[++pivot] == target) right = pivot; 37 | return [left, right]; 38 | } 39 | } 40 | 41 | return [-1, -1]; 42 | }; 43 | // @lc code=end 44 | 45 | export { searchRange }; 46 | -------------------------------------------------------------------------------- /js/problems/344.reverse-string/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = string[]; 6 | type Output = string[]; 7 | 8 | const cases = makeTestCasesOfSingleInput([ 9 | // 10 | { 11 | input: ['h', 'e', 'l', 'l', 'o'], 12 | output: ['o', 'l', 'l', 'e', 'h'], 13 | }, 14 | { 15 | input: ['H', 'a', 'n', 'n', 'a', 'h'], 16 | output: ['h', 'a', 'n', 'n', 'a', 'H'], 17 | }, 18 | { 19 | input: [], 20 | output: [], 21 | }, 22 | { 23 | input: ['a'], 24 | output: ['a'], 25 | }, 26 | ]); 27 | 28 | // * ------------------------------------------------ 29 | 30 | import { reverseString } from './solution'; 31 | testRunner(cases, reverseString); 32 | -------------------------------------------------------------------------------- /js/problems/344.reverse-string/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=344 lang=javascript 3 | * 4 | * [344] Reverse String 5 | */ 6 | /** 7 | * @param {character[]} s 8 | * @return {void} Do not return anything, modify s in-place instead. 9 | */ 10 | const reverseString = (s: string[]): void => { 11 | // * ['104 ms', '98.39 %', '46.9 MB', '33.19 %'] 12 | 13 | if (s.length < 2) return; 14 | 15 | const swap = (str: string[], i: number, j: number) => { 16 | const t = str[i]; 17 | str[i] = str[j]; 18 | str[j] = t; 19 | }; 20 | 21 | let i = 0; 22 | let j = s.length - 1; 23 | 24 | while (i < j) { 25 | swap(s, i, j); 26 | i++, j--; 27 | } 28 | }; 29 | 30 | export { reverseString }; 31 | -------------------------------------------------------------------------------- /js/problems/349.intersection-of-two-arrays/solution-two-pointer.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=349 lang=javascript 3 | * 4 | * [349] Intersection of Two Arrays 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * @param {number[]} nums1 10 | * @param {number[]} nums2 11 | * @return {number[]} 12 | */ 13 | const intersection = (nums1: number[], nums2: number[]): number[] => { 14 | // * ['60 ms', '52.35 %', '35.4 MB', '30.77 %'] 15 | 16 | // * sort is O(n*log(n)) 17 | 18 | nums1 = nums1.sort((a, b) => a - b); 19 | nums2 = nums2.sort((a, b) => a - b); 20 | 21 | const result = new Set(); 22 | 23 | const len1 = nums1.length; 24 | const len2 = nums2.length; 25 | let p1 = 0; 26 | let p2 = 0; 27 | 28 | while (p1 < len1 && p2 < len2) { 29 | if (nums1[p1] < nums2[p2]) { 30 | p1++; 31 | } else if (nums1[p1] > nums2[p2]) { 32 | p2++; 33 | } else { 34 | result.add(nums1[p1]); 35 | p1++; 36 | p2++; 37 | } 38 | } 39 | 40 | return [...result]; 41 | }; 42 | // @lc code=end 43 | 44 | export { intersection }; 45 | -------------------------------------------------------------------------------- /js/problems/349.intersection-of-two-arrays/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=349 lang=javascript 3 | * 4 | * [349] Intersection of Two Arrays 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * @param {number[]} nums1 10 | * @param {number[]} nums2 11 | * @return {number[]} 12 | */ 13 | const intersection = (nums1: number[], nums2: number[]): number[] => { 14 | // * ['48 ms', '97.78 %', '34.1 MB', '92.31 %'] 15 | const set1 = new Set(nums1); 16 | const set2 = new Set(nums2); 17 | 18 | const result: number[] = []; 19 | 20 | set1.forEach((e) => { 21 | if (set2.has(e)) result.push(e); 22 | }); 23 | 24 | return result; 25 | }; 26 | // @lc code=end 27 | 28 | export { intersection }; 29 | -------------------------------------------------------------------------------- /js/problems/349.intersection-of-two-arrays/todo.md: -------------------------------------------------------------------------------- 1 | binary search 2 | 3 | https://leetcode-cn.com/problems/intersection-of-two-arrays/solution/duo-chong-jie-fa-jie-jue-349-liang-ge-shu-zu-de-ji/ 4 | 5 | nums2.sort() 6 | nums1.forEach(binarySearchInNums2) 7 | -------------------------------------------------------------------------------- /js/problems/350.intersection-of-two-arrays-ii/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=350 lang=javascript 3 | * 4 | * [350] Intersection of Two Arrays II 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * @param {number[]} nums1 10 | * @param {number[]} nums2 11 | * @return {number[]} 12 | */ 13 | const intersect = (nums1: number[], nums2: number[]): number[] => { 14 | // * ['48 ms', '98.49 %', '35.3 MB', '55.56 %'] 15 | 16 | // * https://leetcode-cn.com/problems/intersection-of-two-arrays-ii/solution/jin-jie-san-wen-by-user5707f/ 17 | 18 | // * if already sorted, it's O(n), but still need to keep these code 19 | nums1 = nums1.sort((a, b) => a - b); 20 | nums2 = nums2.sort((a, b) => a - b); 21 | 22 | const result: number[] = []; 23 | 24 | const len1 = nums1.length; 25 | const len2 = nums2.length; 26 | let p1 = 0; 27 | let p2 = 0; 28 | 29 | while (p1 < len1 && p2 < len2) { 30 | if (nums1[p1] < nums2[p2]) { 31 | p1++; 32 | } else if (nums1[p1] > nums2[p2]) { 33 | p2++; 34 | } else { 35 | result.push(nums1[p1]); 36 | p1++; 37 | p2++; 38 | } 39 | } 40 | 41 | return [...result]; 42 | }; 43 | // @lc code=end 44 | 45 | export { intersect }; 46 | -------------------------------------------------------------------------------- /js/problems/367.valid-perfect-square/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = number; 6 | type Output = boolean; 7 | 8 | const cases = makeTestCasesOfSingleInput([ 9 | // 10 | { input: 1, output: true }, 11 | { input: 2, output: false }, 12 | { input: 3, output: false }, 13 | { input: 4, output: true }, 14 | { input: 14, output: false }, 15 | { input: 16, output: true }, 16 | 17 | { input: 255, output: false }, 18 | { input: 256, output: true }, 19 | { input: 257, output: false }, 20 | 21 | { input: 511, output: false }, 22 | { input: 512, output: false }, 23 | { input: 513, output: false }, 24 | 25 | { input: 1023, output: false }, 26 | { input: 1024, output: true }, 27 | { input: 1025, output: false }, 28 | 29 | { input: 4294967295, output: false }, 30 | { input: 4294967296, output: true }, 31 | ]); 32 | 33 | // * ------------------------------------------------ 34 | 35 | import { isPerfectSquare } from './solution'; 36 | testRunner(cases, isPerfectSquare); 37 | -------------------------------------------------------------------------------- /js/problems/367.valid-perfect-square/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=367 lang=javascript 3 | * 4 | * [367] Valid Perfect Square 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * @param {number} num 10 | * @return {boolean} 11 | */ 12 | const isPerfectSquare = (num: number): boolean => { 13 | // * ['44 ms', '98.21 %', '33.7 MB', '75 %'] 14 | 15 | if (num === 1) return true; 16 | 17 | let left = 2; 18 | let right = num; 19 | 20 | while (left <= right) { 21 | const mid = Math.floor((left + right) / 2); 22 | const val = mid ** 2; 23 | if (val < num) { 24 | left = mid + 1; 25 | } else if (val > num) { 26 | right = mid - 1; 27 | } else { 28 | return true; 29 | } 30 | } 31 | 32 | return false; 33 | }; 34 | 35 | // @lc code=end 36 | 37 | export { isPerfectSquare }; 38 | -------------------------------------------------------------------------------- /js/problems/374.guess-number-higher-or-lower/do.test.ts: -------------------------------------------------------------------------------- 1 | describe('I dont like this problem', () => { 2 | test('not test, just check 704', () => {}); 3 | }); 4 | -------------------------------------------------------------------------------- /js/problems/374.guess-number-higher-or-lower/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=374 lang=javascript 3 | * 4 | * [374] Guess Number Higher or Lower 5 | */ 6 | 7 | // @lc code=start 8 | 9 | /** 10 | * Forward declaration of guess API. 11 | * @param {number} num your guess 12 | * @return -1 if num is lower than the guess number 13 | * 1 if num is higher than the guess number 14 | * otherwise return 0 15 | * var guess = function(num) {} 16 | */ 17 | 18 | /** 19 | * @param {number} n 20 | * @return {number} 21 | */ 22 | const guessNumber = (n: number): number => { 23 | // * ['52 ms', '73.49 %', '33.6 MB', '100 %'] 24 | 25 | let left = 0; 26 | let right = n; 27 | 28 | let mid = 0; 29 | 30 | while (left <= right) { 31 | mid = ~~((left + right) / 2); 32 | // @ts-ignore 33 | const check = guess(mid); 34 | if (check === 1) { 35 | left = mid + 1; 36 | } else if (check === -1) { 37 | right = mid - 1; 38 | } else { 39 | break; 40 | } 41 | } 42 | 43 | return mid; 44 | }; 45 | // @lc code=end 46 | 47 | export { guessNumber }; 48 | -------------------------------------------------------------------------------- /js/problems/38.count-and-say/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = number; 6 | type Output = string; 7 | 8 | const cases = makeTestCasesOfSingleInput([ 9 | // 10 | 11 | { input: 1, output: '1' }, 12 | { input: 2, output: '11' }, 13 | { input: 3, output: '21' }, 14 | { input: 4, output: '1211' }, 15 | { input: 5, output: '111221' }, 16 | ]); 17 | 18 | // * ------------------------------------------------ 19 | 20 | import { countAndSay } from './solution'; 21 | testRunner(cases, countAndSay); 22 | -------------------------------------------------------------------------------- /js/problems/38.count-and-say/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=38 lang=javascript 3 | * 4 | * [38] Count and Say 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * @param {number} n 10 | * @return {string} 11 | */ 12 | const countAndSay = (n: number): string => { 13 | // * ['52 ms', '89.99 %', '35.7 MB', '33.33 %'] 14 | 15 | let result = '1'; 16 | 17 | for (let i = 1; i < n; i++) { 18 | let nextResult = ''; 19 | let step = 1; 20 | 21 | for (let j = 0; j < result.length; j++) { 22 | if (result[j + 1] === result[j]) { 23 | step++; 24 | } else { 25 | nextResult += `${step}${result[j]}`; 26 | step = 1; 27 | } 28 | } 29 | 30 | result = nextResult; 31 | } 32 | 33 | return result; 34 | }; 35 | // @lc code=end 36 | 37 | export { countAndSay }; 38 | -------------------------------------------------------------------------------- /js/problems/387.first-unique-character-in-a-string/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = string; 6 | type Output = number; 7 | 8 | const cases = makeTestCasesOfSingleInput([ 9 | // 10 | { input: 'leetcode', output: 0 }, 11 | 12 | { input: 'loveleetcode', output: 2 }, 13 | 14 | { input: 'aaaa', output: -1 }, 15 | ]); 16 | 17 | // * ------------------------------------------------ 18 | 19 | import { firstUniqChar } from './solution-map'; 20 | testRunner(cases, firstUniqChar); 21 | 22 | import { firstUniqChar as map } from './solution-map'; 23 | testRunner(cases, map, 'hashmap'); 24 | 25 | import { firstUniqChar as fancy } from './solution-last-index'; 26 | testRunner(cases, fancy, 'fancy js'); 27 | -------------------------------------------------------------------------------- /js/problems/387.first-unique-character-in-a-string/solution-last-index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=387 lang=javascript 3 | * 4 | * [387] First Unique Character in a String 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * @param {string} s 10 | * @return {number} 11 | */ 12 | const firstUniqChar = (s: string): number => { 13 | // * ['80 ms', '93.22 %', '37.9 MB', '77.5 %'] 14 | 15 | for (let i = 0; i < s.length; i++) { 16 | if (s.indexOf(s[i]) === s.lastIndexOf(s[i])) return i; 17 | } 18 | 19 | return -1; 20 | }; 21 | // @lc code=end 22 | 23 | export { firstUniqChar }; 24 | -------------------------------------------------------------------------------- /js/problems/387.first-unique-character-in-a-string/solution-map.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=387 lang=javascript 3 | * 4 | * [387] First Unique Character in a String 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * @param {string} s 10 | * @return {number} 11 | */ 12 | const firstUniqChar = (s: string): number => { 13 | // * ['92 ms', '72.57 %', '38 MB', '77.5 %'] 14 | 15 | const record = new Map(); 16 | 17 | for (let i = 0; i < s.length; i++) { 18 | const char = s[i]; 19 | record.set(char, (record.get(char) || 0) + 1); 20 | } 21 | 22 | for (let i = 0; i < s.length; i++) { 23 | const char = s[i]; 24 | if (record.get(char) === 1) return i; 25 | } 26 | 27 | return -1; 28 | }; 29 | // @lc code=end 30 | 31 | export { firstUniqChar }; 32 | -------------------------------------------------------------------------------- /js/problems/387.first-unique-character-in-a-string/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=387 lang=javascript 3 | * 4 | * [387] First Unique Character in a String 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * @param {string} s 10 | * @return {number} 11 | */ 12 | const firstUniqChar = (s: string): number => { 13 | // * ['60 ms', '99.68 %', '37.9 MB', '77.5 %'] 14 | 15 | const record = new Array(26).fill(0); 16 | 17 | for (let i = 0; i < s.length; i++) { 18 | record[s.charCodeAt(i) - 97] += 1; 19 | } 20 | 21 | for (let i = 0; i < s.length; i++) { 22 | if (record[s.charCodeAt(i) - 97] === 1) return i; 23 | } 24 | 25 | return -1; 26 | }; 27 | // @lc code=end 28 | 29 | export { firstUniqChar }; 30 | -------------------------------------------------------------------------------- /js/problems/394.decode-string/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = string; 6 | type Output = string; 7 | 8 | const cases = makeTestCasesOfSingleInput([ 9 | // 10 | { input: '3[a]2[bc]', output: 'aaabcbc' }, 11 | { input: '3[a2[c]]', output: 'accaccacc' }, 12 | { input: '2[abc]3[cd]ef', output: 'abcabccdcdcdef' }, 13 | 14 | { input: 'qq2[a]2[b]qq', output: 'qqaabbqq' }, 15 | { input: 'q1[a1[b1[c]b]a]q', output: 'qabcbaq' }, 16 | { input: '11[a]', output: 'aaaaaaaaaaa' }, 17 | 18 | { input: '', output: '' }, 19 | ]); 20 | 21 | // * ------------------------------------------------ 22 | 23 | import { decodeString } from './solution'; 24 | testRunner(cases, decodeString); 25 | -------------------------------------------------------------------------------- /js/problems/394.decode-string/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=394 lang=javascript 3 | * 4 | * [394] Decode String 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * @param {string} s 10 | * @return {string} 11 | */ 12 | const decodeString = (s: string): string => { 13 | // * ['48 ms', '88.89 %', '33.8 MB', '83.33 %'] 14 | 15 | const resultArr: string[] = ['']; 16 | const timesStack: number[] = []; 17 | let times = 0; 18 | 19 | for (let i = 0; i < s.length; i++) { 20 | const char = s[i]; 21 | 22 | if (!Number.isNaN(Number(char))) { 23 | times = 10 * times + Number(char); 24 | } else if (char === '[') { 25 | timesStack.push(times); 26 | resultArr.push(''); 27 | times = 0; 28 | } else if (char === ']') { 29 | const times = timesStack.pop()!; 30 | const subStr = resultArr.pop()!; 31 | resultArr[resultArr.length - 1] += subStr.repeat(times); 32 | } else { 33 | resultArr[resultArr.length - 1] += char; 34 | } 35 | } 36 | 37 | return resultArr[0]; 38 | }; 39 | // @lc code=end 40 | 41 | export { decodeString }; 42 | -------------------------------------------------------------------------------- /js/problems/4.median-of-two-sorted-arrays/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = [number[], number[]]; 6 | type Output = number; 7 | 8 | const cases = makeTestCases([ 9 | // 10 | { 11 | input: [[1, 3], [2]], 12 | output: 2.0, 13 | }, 14 | 15 | { 16 | input: [ 17 | [1, 2], 18 | [3, 4], 19 | ], 20 | output: 2.5, 21 | }, 22 | 23 | { 24 | input: [ 25 | [1, 3, 4, 9], 26 | [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 27 | ], 28 | output: 4.5, 29 | }, 30 | 31 | { 32 | input: [ 33 | [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 34 | [1, 3, 4, 9], 35 | ], 36 | output: 4.5, 37 | }, 38 | 39 | { 40 | input: [ 41 | [1, 2], 42 | [3, 4, 5, 6, 7, 8, 9, 10], 43 | ], 44 | output: 5.5, 45 | }, 46 | 47 | { 48 | input: [ 49 | [3, 4, 5, 6, 7, 8, 9, 10], 50 | [1, 2], 51 | ], 52 | output: 5.5, 53 | }, 54 | ]); 55 | 56 | // * ------------------------------------------------ 57 | 58 | // import { findMedianSortedArrays } from './solution'; 59 | // testRunner(cases, findMedianSortedArrays); 60 | -------------------------------------------------------------------------------- /js/problems/4.median-of-two-sorted-arrays/readme.md: -------------------------------------------------------------------------------- 1 | https://leetcode-cn.com/problems/median-of-two-sorted-arrays/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by-w-2/ 2 | -------------------------------------------------------------------------------- /js/problems/48.rotate-image/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Matrix = number[][]; 6 | 7 | type Input = Matrix; 8 | type Output = Matrix; 9 | 10 | const cases = makeTestCasesOfSingleInput([ 11 | // 12 | 13 | { 14 | input: [ 15 | [1, 2, 3], 16 | [4, 5, 6], 17 | [7, 8, 9], 18 | ], 19 | 20 | output: [ 21 | [7, 4, 1], 22 | [8, 5, 2], 23 | [9, 6, 3], 24 | ], 25 | }, 26 | { 27 | input: [ 28 | [5, 1, 9, 11], 29 | [2, 4, 8, 10], 30 | [13, 3, 6, 7], 31 | [15, 14, 12, 16], 32 | ], 33 | 34 | output: [ 35 | [15, 13, 2, 5], 36 | [14, 3, 4, 1], 37 | [12, 6, 8, 9], 38 | [16, 7, 10, 11], 39 | ], 40 | }, 41 | ]); 42 | 43 | // * ------------------------------------------------ 44 | 45 | import { rotate } from './solution'; 46 | testRunner(cases, rotate); 47 | -------------------------------------------------------------------------------- /js/problems/48.rotate-image/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=48 lang=javascript 3 | * 4 | * [48] Rotate Image 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * @param {number[][]} matrix 10 | * @return {void} Do not return anything, modify matrix in-place instead. 11 | */ 12 | const rotate = (matrix: number[][]): void => { 13 | // * ['52 ms', '82.11 %', '33.7 MB', '100 %'] 14 | 15 | const n = matrix.length; 16 | const end = n - 1; 17 | const loop1 = Math.ceil(n / 2); 18 | const loop2 = Math.floor(n / 2); 19 | 20 | for (let row = 0; row < loop1; row++) { 21 | for (let col = 0; col < loop2; col++) { 22 | const temp = matrix[row][col]; 23 | matrix[row][col] = matrix[end - col][row]; 24 | matrix[end - col][row] = matrix[end - row][end - col]; 25 | matrix[end - row][end - col] = matrix[col][end - row]; 26 | matrix[col][end - row] = temp; 27 | } 28 | } 29 | }; 30 | // @lc code=end 31 | 32 | export { rotate }; 33 | -------------------------------------------------------------------------------- /js/problems/485.max-consecutive-ones/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = number[]; 6 | type Output = number; 7 | 8 | const cases = makeTestCasesOfSingleInput([ 9 | // 10 | { 11 | input: [1, 1, 0, 1, 1, 1], 12 | output: 3, 13 | }, 14 | { 15 | input: [1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1], 16 | output: 3, 17 | }, 18 | { 19 | input: [], 20 | output: 0, 21 | }, 22 | { 23 | input: [0], 24 | output: 0, 25 | }, 26 | { 27 | input: [1], 28 | output: 1, 29 | }, 30 | ]); 31 | 32 | // * ------------------------------------------------ 33 | 34 | import { findMaxConsecutiveOnes } from './solution'; 35 | testRunner(cases, findMaxConsecutiveOnes); 36 | -------------------------------------------------------------------------------- /js/problems/485.max-consecutive-ones/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=485 lang=javascript 3 | * 4 | * [485] Max Consecutive Ones 5 | */ 6 | /** 7 | * @param {number[]} nums 8 | * @return {number} 9 | */ 10 | const findMaxConsecutiveOnes = (nums: number[]): number => { 11 | let max = 0; 12 | 13 | let p1 = -1; 14 | 15 | for (let p2 = 0; p2 < nums.length; p2++) { 16 | if (nums[p2] === 1) { 17 | max = Math.max(max, p2 - p1); 18 | } else { 19 | p1 = p2; 20 | } 21 | } 22 | 23 | return max; 24 | }; 25 | 26 | export { findMaxConsecutiveOnes }; 27 | -------------------------------------------------------------------------------- /js/problems/494.target-sum/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = [number[], number]; 6 | type Output = number; 7 | 8 | const cases = makeTestCases([ 9 | // 10 | { 11 | input: [[1, 1, 1, 1, 1], 3], 12 | output: 5, 13 | }, 14 | { 15 | input: [[1], 2], 16 | output: 0, 17 | }, 18 | { 19 | input: [[1, 2, 3], 999], 20 | output: 0, 21 | }, 22 | ]); 23 | 24 | // * ------------------------------------------------ 25 | 26 | import { findTargetSumWays } from './solution'; 27 | 28 | testRunner(cases, findTargetSumWays); 29 | -------------------------------------------------------------------------------- /js/problems/494.target-sum/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=494 lang=javascript 3 | * 4 | * [494] Target Sum 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * @param {number[]} nums 10 | * @param {number} S 11 | * @return {number} 12 | */ 13 | const findTargetSumWays = (nums: number[], S: number): number => { 14 | // * dp ['188 ms', '71.81 %', '39.5 MB', '100 %'] 15 | // * https://leetcode-cn.com/problems/target-sum/solution/mu-biao-he-by-leetcode/ 16 | 17 | let pool = new Map(); 18 | pool.set(0, 1); 19 | 20 | nums.forEach((n, i) => { 21 | const nextPool = new Map(); 22 | pool.forEach((step, sum) => { 23 | nextPool.set(sum + n, (nextPool.get(sum + n) || 0) + step); 24 | nextPool.set(sum - n, (nextPool.get(sum - n) || 0) + step); 25 | }); 26 | pool = nextPool; 27 | }); 28 | return pool.get(S) || 0; 29 | }; 30 | // @lc code=end 31 | 32 | export { findTargetSumWays }; 33 | -------------------------------------------------------------------------------- /js/problems/498.diagonal-traverse/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = number[][]; 6 | type Output = number[]; 7 | 8 | const cases = makeTestCasesOfSingleInput([ 9 | // 10 | { 11 | input: [ 12 | [1, 2, 3], 13 | [4, 5, 6], 14 | [7, 8, 9], 15 | ], 16 | output: [1, 2, 4, 7, 5, 3, 6, 8, 9], 17 | }, 18 | { 19 | input: [ 20 | [1, 2], 21 | [4, 5], 22 | [7, 8], 23 | ], 24 | output: [1, 2, 4, 7, 5, 8], 25 | }, 26 | { 27 | input: [ 28 | [1, 2, 3], 29 | [4, 5, 6], 30 | ], 31 | output: [1, 2, 4, 5, 3, 6], 32 | }, 33 | { 34 | input: [[1, 2, 3]], 35 | output: [1, 2, 3], 36 | }, 37 | { 38 | input: [[1], [2], [3]], 39 | output: [1, 2, 3], 40 | }, 41 | { 42 | input: [], 43 | output: [], 44 | }, 45 | { 46 | input: [[]], 47 | output: [], 48 | }, 49 | ]); 50 | 51 | // * ------------------------------------------------ 52 | 53 | import { findDiagonalOrder } from './solution'; 54 | testRunner(cases, findDiagonalOrder); 55 | -------------------------------------------------------------------------------- /js/problems/498.diagonal-traverse/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=498 lang=javascript 3 | * 4 | * [498] Diagonal Traverse 5 | */ 6 | /** 7 | * @param {number[][]} matrix 8 | * @return {number[]} 9 | */ 10 | const findDiagonalOrder = (matrix: number[][]): number[] => { 11 | // * empty 12 | if (!matrix.length || !matrix[0].length) return []; 13 | // * one line 14 | if (matrix.length === 1) return [...matrix[0]]; 15 | // * one row 16 | if (matrix[0].length === 1) return matrix.map((e) => e[0]); 17 | 18 | const rowMax = matrix.length - 1; 19 | const columnMax = matrix[0].length - 1; 20 | const result = []; 21 | 22 | let row = 1; 23 | let column = -1; 24 | let up = true; 25 | 26 | // * walk 27 | while (!(row === rowMax && column === columnMax)) { 28 | if (up) row--, column++; 29 | else row++, column--; 30 | 31 | if (row < 0 || column > columnMax) { 32 | up = false; 33 | row++; 34 | if (column > columnMax) row++, column--; 35 | } else if (row > rowMax || column < 0) { 36 | up = true; 37 | column++; 38 | if (row > rowMax) row--, column++; 39 | } 40 | 41 | result.push(matrix[row][column]); 42 | } 43 | 44 | return result; 45 | }; 46 | 47 | export { findDiagonalOrder }; 48 | -------------------------------------------------------------------------------- /js/problems/5.longest-palindromic-substring/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = string; 6 | type Output = string; 7 | 8 | const cases = makeTestCasesOfSingleInput([ 9 | // 10 | { input: 'babad', output: 'bab' }, 11 | { input: 'cbbd', output: 'bb' }, 12 | { input: 'a', output: 'a' }, 13 | 14 | { input: 'ac', output: 'a' }, 15 | { input: '', output: '' }, 16 | ]); 17 | 18 | // * ------------------------------------------------ 19 | 20 | import { longestPalindrome } from './solution'; 21 | testRunner(cases, longestPalindrome); 22 | -------------------------------------------------------------------------------- /js/problems/5.longest-palindromic-substring/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=5 lang=javascript 3 | * 4 | * [5] Longest Palindromic Substring 5 | */ 6 | // @lc code=start 7 | /** 8 | * @param {string} s 9 | * @return {string} 10 | */ 11 | const longestPalindrome = (s: string): string => { 12 | if (s.length < 2) return s; 13 | 14 | let [r1, r2, max] = [0, 0, 0]; 15 | const end = s.length - 1; 16 | 17 | const search = (s: string, a: number, b: number) => { 18 | while (0 <= a && b <= end && s[a] === s[b]) { 19 | if (b - a > max) { 20 | [r1, r2, max] = [a, b, b - a]; 21 | } 22 | a--; 23 | b++; 24 | } 25 | }; 26 | 27 | for (let i = 0; i <= end - 2; i++) { 28 | search(s, i, i + 1); 29 | search(s, i, i + 2); 30 | } 31 | search(s, end - 1, end); 32 | 33 | return s.slice(r1, r2 + 1); 34 | }; 35 | // @lc code=end 36 | 37 | export { longestPalindrome }; 38 | -------------------------------------------------------------------------------- /js/problems/50.pow-x-n/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = [number, number]; 6 | type Output = number; 7 | 8 | const cases = makeTestCases([ 9 | // 10 | { input: [2.0, 10], output: 1024.0 }, 11 | { input: [2.0, -2], output: 0.25 }, 12 | 13 | // TODO fix this later, now manually passing // Seognil LC 2020/03/11 14 | // { input: [2.1, 3], output: 9.261 }, 15 | { input: [2.1, 3], output: 9.261000000000001 }, 16 | ]); 17 | 18 | // * ------------------------------------------------ 19 | 20 | import { myPow } from './solution'; 21 | testRunner(cases, myPow); 22 | -------------------------------------------------------------------------------- /js/problems/50.pow-x-n/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=50 lang=javascript 3 | * 4 | * [50] Pow(x, n) 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * @param {number} x 10 | * @param {number} n 11 | * @return {number} 12 | */ 13 | const myPow = (x: number, n: number): number => { 14 | // * ['52 ms', '93.37 %', '33.9 MB', '52.94 %'] 15 | 16 | // * n is integer 17 | 18 | if (n === 0) return 1; 19 | return n < 0 ? 1 / p(x, -n, 1) : p(x, n, 1); 20 | }; 21 | 22 | const p = (x: number, n: number, rest: number): number => { 23 | if (n === 1) return x * rest; 24 | return n % 2 === 0 ? p(x * x, n / 2, rest) : p(x * x, (n - 1) / 2, rest * x); 25 | }; 26 | // @lc code=end 27 | 28 | export { myPow }; 29 | -------------------------------------------------------------------------------- /js/problems/509.fibonacci-number/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = number; 6 | type Output = number; 7 | 8 | const cases = makeTestCasesOfSingleInput([ 9 | // 10 | { input: 0, output: 0 }, 11 | { input: 1, output: 1 }, 12 | { input: 2, output: 1 }, 13 | { input: 3, output: 2 }, 14 | { input: 4, output: 3 }, 15 | { input: 5, output: 5 }, 16 | { input: 6, output: 8 }, 17 | { input: 7, output: 13 }, 18 | 19 | { input: 20, output: 6765 }, 20 | { input: 30, output: 832040 }, 21 | { input: 40, output: 102334155 }, 22 | ]); 23 | 24 | // * ------------------------------------------------ 25 | 26 | import { fib } from './solution'; 27 | testRunner(cases, fib); 28 | -------------------------------------------------------------------------------- /js/problems/509.fibonacci-number/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=509 lang=javascript 3 | * 4 | * [509] Fibonacci Number 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * @param {number} N 10 | * @return {number} 11 | */ 12 | const fib = (N: number): number => { 13 | // * ['48 ms', '92.72 %', '33.8 MB', '100 %'] 14 | 15 | if (N < 2) return N; 16 | 17 | if (!history[N]) history[N] = fib(N - 1) + fib(N - 2); 18 | 19 | return history[N]; 20 | }; 21 | 22 | const history: Record = { 0: 0, 1: 1 }; 23 | 24 | // @lc code=end 25 | 26 | export { fib }; 27 | -------------------------------------------------------------------------------- /js/problems/52.n-queens-ii/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = number; 6 | type Output = number; 7 | 8 | const cases = makeTestCasesOfSingleInput([ 9 | // 10 | { 11 | input: 1, 12 | output: 1, 13 | }, 14 | { 15 | input: 3, 16 | output: 0, 17 | }, 18 | { 19 | input: 4, 20 | output: 2, 21 | }, 22 | { 23 | input: 5, 24 | output: 10, 25 | }, 26 | ]); 27 | 28 | // * ------------------------------------------------ 29 | 30 | import { totalNQueens } from './solution'; 31 | testRunner(cases, totalNQueens); 32 | -------------------------------------------------------------------------------- /js/problems/52.n-queens-ii/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=52 lang=javascript 3 | * 4 | * [52] N-Queens II 5 | */ 6 | 7 | // @lc code=start 8 | 9 | type RowQIndexList = (number | undefined)[]; 10 | 11 | /** 12 | * @param {number} n 13 | * @return {number} 14 | */ 15 | const totalNQueens = (n: number): number => { 16 | // * ['60 ms', '80.28 %', '34.3 MB', '100 %'] 17 | 18 | const queens: RowQIndexList = new Array(n); 19 | let results = 0; 20 | 21 | const loopRun = (queens: RowQIndexList, row = 0): void => { 22 | // * filled as solved, push valid solution 23 | if (queens[n - 1] !== undefined) { 24 | results += 1; 25 | return; 26 | } 27 | 28 | for (let i = 0; i < n; i++) { 29 | queens[row] = i; 30 | if (checkQueens(queens, row)) { 31 | loopRun(queens, row + 1); 32 | } 33 | queens[row] = undefined; 34 | } 35 | }; 36 | 37 | loopRun(queens); 38 | 39 | return results; 40 | }; 41 | 42 | const checkQueens = (queens: RowQIndexList, row: number): boolean => { 43 | const e = queens[row]; 44 | 45 | for (let i = 0; i < row; i++) { 46 | const k = queens[i]!; 47 | if (k === e || k - row + i === e || k + row - i === e) return false; 48 | } 49 | return true; 50 | }; 51 | 52 | // @lc code=end 53 | 54 | export { totalNQueens }; 55 | -------------------------------------------------------------------------------- /js/problems/539.minimum-time-difference/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = string[]; 6 | type Output = number; 7 | 8 | const cases = makeTestCasesOfSingleInput([ 9 | // 10 | { 11 | input: ['23:59', '00:00'], 12 | output: 1, 13 | }, 14 | { 15 | input: ['11:20', '12:21'], 16 | output: 61, 17 | }, 18 | { 19 | input: ['00:55', '12:56'], 20 | output: 719, 21 | }, 22 | { 23 | input: ['00:55', '00:55'], 24 | output: 0, 25 | }, 26 | { 27 | input: ['1:01', '2:03', '3:03', '4:03', '5:05', '6:06', '7:07', '8:08'], 28 | output: 60, 29 | }, 30 | { 31 | input: ['3:03', '8:08', '5:05', '2:03', '1:01', '6:06', '4:03', '7:07'], 32 | output: 60, 33 | }, 34 | ]); 35 | 36 | // * ------------------------------------------------ 37 | 38 | import { findMinDifference } from './solution'; 39 | testRunner(cases, findMinDifference); 40 | -------------------------------------------------------------------------------- /js/problems/539.minimum-time-difference/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=539 lang=javascript 3 | * 4 | * [539] Minimum Time Difference 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * @param {string[]} timePoints 10 | * @return {number} 11 | */ 12 | const findMinDifference = (timePoints: string[]): number => { 13 | // * ['84 ms', '85.42 %', '38.7 MB', '100 %'] 14 | 15 | const len = timePoints.length; 16 | 17 | const mins = timePoints.map(mapTimeToMin).sort((a, b) => a - b); 18 | 19 | let min = Infinity; 20 | for (let i = 1; i < len; i++) { 21 | min = Math.min(min, mins[i] - mins[i - 1]); 22 | } 23 | min = Math.min(min, mins[0] + 24 * 60 - mins[len - 1]); 24 | 25 | return min; 26 | }; 27 | 28 | const mapTimeToMin = (e: string): number => { 29 | const [h, m] = e.split(':'); 30 | return Number(h) * 60 + Number(m); 31 | }; 32 | // @lc code=end 33 | 34 | export { findMinDifference }; 35 | -------------------------------------------------------------------------------- /js/problems/54.spiral-matrix/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=54 lang=javascript 3 | * 4 | * [54] Spiral Matrix 5 | */ 6 | /** 7 | * @param {number[][]} matrix 8 | * @return {number[]} 9 | */ 10 | const spiralOrder = (matrix: number[][]): number[] => { 11 | // * empty 12 | if (!matrix.length || !matrix[0].length) return []; 13 | // * one line 14 | if (matrix.length === 1) return [...matrix[0]]; 15 | // * one row 16 | if (matrix[0].length === 1) return matrix.map((e) => e[0]); 17 | 18 | const result = []; 19 | 20 | let row = 0; 21 | let column = -1; 22 | let rowMax = matrix.length; 23 | let columnMax = matrix[0].length; 24 | 25 | // * walk 26 | while (rowMax > 0 && columnMax > 0) { 27 | for (let i = 0; i < columnMax; i++) result.push(matrix[row][++column]); 28 | 29 | if (rowMax == 1) break; 30 | 31 | for (let i = 0; i < rowMax - 1; i++) result.push(matrix[++row][column]); 32 | for (let i = 0; i < columnMax - 1; i++) result.push(matrix[row][--column]); 33 | 34 | if (columnMax == 1) break; 35 | 36 | for (let i = 0; i < rowMax - 2; i++) result.push(matrix[--row][column]); 37 | 38 | rowMax -= 2; 39 | columnMax -= 2; 40 | } 41 | 42 | return result; 43 | }; 44 | 45 | export { spiralOrder }; 46 | -------------------------------------------------------------------------------- /js/problems/557.reverse-words-in-a-string-iii/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = string; 6 | type Output = string; 7 | 8 | const cases = makeTestCasesOfSingleInput([ 9 | // 10 | { 11 | input: "Let's take LeetCode contest", 12 | output: "s'teL ekat edoCteeL tsetnoc", 13 | }, 14 | ]); 15 | 16 | // * ------------------------------------------------ 17 | 18 | import { reverseWords } from './solution'; 19 | testRunner(cases, reverseWords); 20 | -------------------------------------------------------------------------------- /js/problems/557.reverse-words-in-a-string-iii/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=557 lang=javascript 3 | * 4 | * [557] Reverse Words in a String III 5 | */ 6 | /** 7 | * @param {string} s 8 | * @return {string} 9 | */ 10 | const reverseWords = (s: string): string => { 11 | // * super easy js way 12 | // TODO try another method later // Seognil LC 2020/03/01 13 | 14 | return s 15 | .split(' ') 16 | .filter((e) => e) 17 | .map((e) => e.split('').reverse().join('')) 18 | .join(' '); 19 | }; 20 | 21 | export { reverseWords }; 22 | -------------------------------------------------------------------------------- /js/problems/561.array-partition-i/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = number[]; 6 | type Output = number; 7 | 8 | const cases = makeTestCasesOfSingleInput([ 9 | // 10 | { 11 | input: [1, 4, 3, 2], 12 | output: 4, 13 | }, 14 | { 15 | input: [], 16 | output: 0, 17 | }, 18 | { 19 | input: [1, 2], 20 | output: 1, 21 | }, 22 | ]); 23 | 24 | // * ------------------------------------------------ 25 | 26 | import { arrayPairSum } from './solution'; 27 | testRunner(cases, arrayPairSum); 28 | -------------------------------------------------------------------------------- /js/problems/561.array-partition-i/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=561 lang=javascript 3 | * 4 | * [561] Array Partition I 5 | */ 6 | /** 7 | * @param {number[]} nums 8 | * @return {number} 9 | */ 10 | const arrayPairSum = (nums: number[]): number => 11 | nums.sort((a, b) => a - b).reduce((a, e, i) => (i % 2 ? a : a + e), 0); 12 | 13 | export { arrayPairSum }; 14 | -------------------------------------------------------------------------------- /js/problems/59.spiral-matrix-ii/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = number; 6 | type Output = number[][]; 7 | 8 | const cases = makeTestCasesOfSingleInput([ 9 | // 10 | { 11 | input: 0, 12 | output: [], 13 | }, 14 | { 15 | input: 1, 16 | output: [[1]], 17 | }, 18 | { 19 | input: 2, 20 | output: [ 21 | [1, 2], 22 | [4, 3], 23 | ], 24 | }, 25 | { 26 | input: 3, 27 | output: [ 28 | [1, 2, 3], 29 | [8, 9, 4], 30 | [7, 6, 5], 31 | ], 32 | }, 33 | { 34 | input: 4, 35 | output: [ 36 | [1, 2, 3, 4], 37 | [12, 13, 14, 5], 38 | [11, 16, 15, 6], 39 | [10, 9, 8, 7], 40 | ], 41 | }, 42 | ]); 43 | 44 | // * ------------------------------------------------ 45 | 46 | import { generateMatrix } from './solution'; 47 | testRunner(cases, generateMatrix); 48 | -------------------------------------------------------------------------------- /js/problems/59.spiral-matrix-ii/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=59 lang=javascript 3 | * 4 | * [59] Spiral Matrix II 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * @param {number} n 10 | * @return {number[][]} 11 | */ 12 | const generateMatrix = (n: number): number[][] => { 13 | // * ['52 ms', '92.84 %', '33.9 MB', '37.5 %'] 14 | 15 | // * if invalid 16 | if (n < 1) return []; 17 | 18 | // * ---------------- 19 | 20 | const result = Array.from({ length: n }, () => Array(n)); 21 | 22 | let count = 0; 23 | let r = 0; 24 | let c = -1; 25 | let step = n; 26 | 27 | while (step > 0) { 28 | for (let i = 0; i < step; i++) result[r][++c] = ++count; 29 | for (let i = 0; i < step - 1; i++) result[++r][c] = ++count; 30 | for (let i = 0; i < step - 1; i++) result[r][--c] = ++count; 31 | for (let i = 0; i < step - 2; i++) result[--r][c] = ++count; 32 | 33 | step -= 2; 34 | } 35 | 36 | return result; 37 | }; 38 | // @lc code=end 39 | 40 | export { generateMatrix }; 41 | -------------------------------------------------------------------------------- /js/problems/622.design-circular-queue/types.d.ts: -------------------------------------------------------------------------------- 1 | export interface CircularQueueConstructor { 2 | new (k: number): CircularQueue; 3 | } 4 | export interface CircularQueue { 5 | enQueue(value: number): boolean; 6 | deQueue(): boolean; 7 | Front(): number; 8 | Rear(): number; 9 | isEmpty(): boolean; 10 | isFull(): boolean; 11 | } 12 | -------------------------------------------------------------------------------- /js/problems/658.find-k-closest-elements/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = [number[], number, number]; 6 | type Output = number[]; 7 | 8 | const cases = makeTestCases([ 9 | // 10 | { 11 | input: [[1, 2, 3, 4, 5], 4, 3], 12 | output: [1, 2, 3, 4], 13 | }, 14 | 15 | { 16 | input: [[1, 2, 3, 4, 5], 2, -1], 17 | output: [1, 2], 18 | }, 19 | { 20 | input: [[1, 2, 3, 4, 5], 2, 99], 21 | output: [4, 5], 22 | }, 23 | 24 | { 25 | input: [[1, 2, 3, 40, 41, 42, 43], 3, 40], 26 | output: [40, 41, 42], 27 | }, 28 | 29 | { 30 | input: [[1, 3, 5, 7, 9], 2, 4], 31 | output: [3, 5], 32 | }, 33 | 34 | { 35 | input: [[1, 2, 3, 4, 5], 2, 3], 36 | output: [2, 3], 37 | }, 38 | { 39 | input: [[1, 2, 3, 4, 5], 3, 3], 40 | output: [2, 3, 4], 41 | }, 42 | { 43 | input: [[1, 2, 3, 4, 5], 4, 3], 44 | output: [1, 2, 3, 4], 45 | }, 46 | ]); 47 | 48 | // * ------------------------------------------------ 49 | 50 | import { findClosestElements } from './solution'; 51 | testRunner(cases, findClosestElements); 52 | -------------------------------------------------------------------------------- /js/problems/658.find-k-closest-elements/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=658 lang=javascript 3 | * 4 | * [658] Find K Closest Elements 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * @param {number[]} arr 10 | * @param {number} k 11 | * @param {number} x 12 | * @return {number[]} 13 | */ 14 | const findClosestElements = (arr: number[], k: number, x: number): number[] => { 15 | // * ['88 ms', '88.12 %', '40.4 MB', '100 %'] 16 | 17 | let left = 0; 18 | let right = arr.length - k; 19 | 20 | while (left < right) { 21 | const mid = ~~((left + right) / 2); 22 | 23 | // * https://www.cnblogs.com/grandyang/p/7519466.html 24 | if (x - arr[mid] > arr[mid + k] - x) { 25 | left = mid + 1; 26 | } else { 27 | right = mid; 28 | } 29 | } 30 | 31 | return arr.slice(left, left + k); 32 | }; 33 | // @lc code=end 34 | 35 | export { findClosestElements }; 36 | -------------------------------------------------------------------------------- /js/problems/66.plus-one/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = number[]; 6 | type Output = number[]; 7 | 8 | const cases = makeTestCasesOfSingleInput([ 9 | // 10 | { 11 | input: [1, 2, 3], 12 | output: [1, 2, 4], 13 | }, 14 | { 15 | input: [4, 3, 2, 1], 16 | output: [4, 3, 2, 2], 17 | }, 18 | { 19 | input: [9, 9, 9, 9], 20 | output: [1, 0, 0, 0, 0], 21 | }, 22 | { 23 | input: [9], 24 | output: [1, 0], 25 | }, 26 | ]); 27 | 28 | // * ------------------------------------------------ 29 | 30 | import { plusOne } from './solution'; 31 | import { plusOne as solution2 } from './solution'; 32 | testRunner(cases, plusOne); 33 | testRunner(cases, solution2, 'solution2'); 34 | -------------------------------------------------------------------------------- /js/problems/66.plus-one/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=66 lang=javascript 3 | * 4 | * [66] Plus One 5 | */ 6 | /** 7 | * @param {number[]} digits 8 | * @return {number[]} 9 | */ 10 | const plusOne = (digits: number[]): number[] => { 11 | // * inplace 12 | 13 | let len = digits.length, 14 | carry = 0; 15 | 16 | digits[len - 1] += 1; 17 | for (let i = len - 1; i >= 0; i--) { 18 | const e = digits[i]; 19 | const sum = e + carry; 20 | carry = sum >= 10 ? 1 : 0; 21 | digits[i] = sum % 10; 22 | } 23 | 24 | carry && digits.unshift(1); 25 | 26 | return digits; 27 | }; 28 | 29 | export { plusOne }; 30 | -------------------------------------------------------------------------------- /js/problems/66.plus-one/solution2.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=66 lang=javascript 3 | * 4 | * [66] Plus One 5 | */ 6 | /** 7 | * @param {number[]} digits 8 | * @return {number[]} 9 | */ 10 | const plusOne = (digits: number[]): number[] => { 11 | // ! this problem seems must to be solved inplace 12 | // ! my local test did passed, but OJ would not 13 | 14 | // * more js and immutable 15 | 16 | const revArr = [...digits].reverse(); 17 | 18 | let carry = 1; 19 | 20 | revArr.map((e, i) => { 21 | const added = e + carry; 22 | carry = added < 10 ? 0 : added - 10; 23 | return added % 10; 24 | }); 25 | 26 | carry != 0 && revArr.push(carry); 27 | 28 | return revArr.reverse(); 29 | }; 30 | 31 | export { plusOne }; 32 | -------------------------------------------------------------------------------- /js/problems/67.add-binary/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = [string, string]; 6 | type Output = string; 7 | 8 | const cases = makeTestCases([ 9 | // 10 | { 11 | input: ['11', '1'], 12 | output: '100', 13 | }, 14 | { 15 | input: ['1010', '1011'], 16 | output: '10101', 17 | }, 18 | { 19 | input: ['', ''], 20 | output: '0', 21 | }, 22 | { 23 | input: ['', '1'], 24 | output: '1', 25 | }, 26 | { 27 | input: ['', '0'], 28 | output: '0', 29 | }, 30 | ]); 31 | 32 | // * ------------------------------------------------ 33 | 34 | import { addBinary } from './solution'; 35 | testRunner(cases, addBinary); 36 | -------------------------------------------------------------------------------- /js/problems/67.add-binary/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=67 lang=javascript 3 | * 4 | * [67] Add Binary 5 | */ 6 | /** 7 | * @param {string} a 8 | * @param {string} b 9 | * @return {string} 10 | */ 11 | const addBinary = (a: string, b: string): string => { 12 | if (a === '' && b === '') return '0'; 13 | 14 | const maxLen = Math.max(a.length, b.length); 15 | 16 | const aRemainLen = a.length - maxLen; 17 | const bRemainLen = b.length - maxLen; 18 | 19 | let result = ''; 20 | let carry = 0; 21 | 22 | for (let point = maxLen - 1; point >= 0; point--) { 23 | const aCarry = Number(a[aRemainLen + point] || 0); 24 | const bCarry = Number(b[bRemainLen + point] || 0); 25 | const subSum = aCarry + bCarry + carry; 26 | carry = subSum >> 1; 27 | result = (subSum % 2) + result; 28 | } 29 | 30 | if (carry) result = '1' + result; 31 | 32 | return result; 33 | }; 34 | 35 | export { addBinary }; 36 | -------------------------------------------------------------------------------- /js/problems/69.sqrt-x/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = number; 6 | type Output = number; 7 | 8 | const cases = makeTestCasesOfSingleInput([ 9 | // 10 | 11 | { input: 0, output: 0 }, 12 | { input: 1, output: 1 }, 13 | { input: 2, output: 1 }, 14 | { input: 3, output: 1 }, 15 | { input: 4, output: 2 }, 16 | { input: 5, output: 2 }, 17 | { input: 6, output: 2 }, 18 | { input: 7, output: 2 }, 19 | { input: 8, output: 2 }, 20 | { input: 9, output: 3 }, 21 | { input: 10, output: 3 }, 22 | 23 | { input: 1073741824, output: 32768 }, 24 | { input: 1073741824, output: 32768 }, 25 | { input: 1073741823, output: 32767 }, 26 | ]); 27 | 28 | // * ------------------------------------------------ 29 | 30 | import { mySqrt } from './solution'; 31 | testRunner(cases, mySqrt); 32 | 33 | import { mySqrt as newton } from './solution-newton-int'; 34 | testRunner(cases, newton, 'newton'); 35 | -------------------------------------------------------------------------------- /js/problems/69.sqrt-x/solution-newton-int.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=69 lang=javascript 3 | * 4 | * [69] Sqrt(x) 5 | */ 6 | 7 | type Int = number; 8 | 9 | // @lc code=start 10 | /** 11 | * @param {number} x 12 | * @return {number} 13 | */ 14 | const mySqrt = (x: Int): Int => { 15 | // * ['68 ms', '88.05 %', '35.5 MB', '94.44 %'] 16 | // * find interger sqrt 17 | // * Newton's method, mock int divide 18 | 19 | if (x < 2) return x; 20 | 21 | let cur: Int = x; 22 | 23 | while (true) { 24 | const next: Int = divide(cur + divide(x, cur), 2); 25 | if (next >= cur) break; 26 | cur = next; 27 | } 28 | 29 | return cur; 30 | }; 31 | 32 | const divide = (x: Int, y: Int): Int => Math.floor(x / y); 33 | 34 | // @lc code=end 35 | 36 | export { mySqrt }; 37 | -------------------------------------------------------------------------------- /js/problems/69.sqrt-x/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=69 lang=javascript 3 | * 4 | * [69] Sqrt(x) 5 | */ 6 | 7 | type Int = number; 8 | type Double = number; 9 | 10 | // @lc code=start 11 | /** 12 | * @param {number} x 13 | * @return {number} 14 | */ 15 | const mySqrt = (x: Int): Int => { 16 | // * ['64 ms', '94.8 %', '35.8 MB', '33.33 %'] 17 | // * find interger sqrt 18 | // * Newton's method 19 | 20 | if (x < 2) return x; 21 | 22 | let cur: Double = x; 23 | 24 | while (true) { 25 | const next: Double = (cur + x / cur) / 2; 26 | if (Math.abs(next - cur) < 1e-6) break; 27 | cur = next; 28 | } 29 | 30 | return Math.floor(cur) as Int; 31 | }; 32 | 33 | // @lc code=end 34 | 35 | export { mySqrt }; 36 | -------------------------------------------------------------------------------- /js/problems/7.reverse-integer/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = number; 6 | type Output = number; 7 | 8 | const cases = makeTestCasesOfSingleInput([ 9 | // 10 | { input: 123, output: 321 }, 11 | { input: -123, output: -321 }, 12 | { input: 120, output: 21 }, 13 | 14 | { input: 4294967296, output: 0 }, 15 | { input: 0, output: 0 }, 16 | ]); 17 | 18 | // * ------------------------------------------------ 19 | 20 | import { reverse } from './solution'; 21 | testRunner(cases, reverse); 22 | -------------------------------------------------------------------------------- /js/problems/7.reverse-integer/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=7 lang=javascript 3 | * 4 | * [7] Reverse Integer 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * @param {number} x 10 | * @return {number} 11 | */ 12 | const reverse = (x: number): number => { 13 | // * ['64 ms', '96.6 %', '35.5 MB', '92.71 %'] 14 | 15 | if (x == 0) return 0; 16 | 17 | const sign = Math.sign(x); 18 | x = Math.abs(x); 19 | let result = 0; 20 | 21 | while (x !== 0) { 22 | result = result * 10 + (x % 10); 23 | x = ~~(x / 10); 24 | } 25 | 26 | if (result > ~(1 << 31) || result < 1 << 31) { 27 | return 0; 28 | } else { 29 | return sign * result; 30 | } 31 | }; 32 | // @lc code=end 33 | 34 | export { reverse }; 35 | -------------------------------------------------------------------------------- /js/problems/70.climbing-stairs/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = number; 6 | type Output = number; 7 | 8 | const cases = makeTestCasesOfSingleInput([ 9 | // 10 | 11 | { input: 1, output: 1 }, 12 | { input: 2, output: 2 }, 13 | { input: 3, output: 3 }, 14 | { input: 4, output: 5 }, 15 | { input: 5, output: 8 }, 16 | { input: 6, output: 13 }, 17 | ]); 18 | 19 | // * ------------------------------------------------ 20 | 21 | import { climbStairs } from './solution'; 22 | testRunner(cases, climbStairs); 23 | -------------------------------------------------------------------------------- /js/problems/70.climbing-stairs/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=70 lang=javascript 3 | * 4 | * [70] Climbing Stairs 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * @param {number} n 10 | * @return {number} 11 | */ 12 | const climbStairs = (n: number): number => { 13 | // * '52 ms', '72.67 %', '33.7 MB', '92 %'] 14 | 15 | if (n < 3) return n; 16 | 17 | if (!history[n]) history[n] = climbStairs(n - 1) + climbStairs(n - 2); 18 | 19 | return history[n]; 20 | }; 21 | 22 | const history: Record = {}; 23 | // @lc code=end 24 | 25 | export { climbStairs }; 26 | -------------------------------------------------------------------------------- /js/problems/700.search-in-a-binary-search-tree/do.test.ts: -------------------------------------------------------------------------------- 1 | import { arrayToTree } from '../../structures/tree/tree-to-array'; 2 | import { TreeNode } from './../../structures/tree/tree-node'; 3 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 4 | 5 | // * ------------------------------------------------ 6 | 7 | type Input = [TreeNode | null, number]; 8 | type Output = TreeNode | null; 9 | 10 | const a2t = arrayToTree; 11 | 12 | const cases = makeTestCases([ 13 | // 14 | { 15 | input: [a2t([4, 2, 7, 1, 3]), 2], 16 | output: a2t([2, 1, 3]), 17 | }, 18 | { 19 | input: [a2t([4, 2, 7, 1, 3]), 5], 20 | output: a2t([]), 21 | }, 22 | { 23 | input: [a2t([]), 5], 24 | output: a2t([]), 25 | }, 26 | ]); 27 | 28 | // * ------------------------------------------------ 29 | 30 | import { searchBST } from './solution-bfs'; 31 | testRunner(cases, searchBST); 32 | 33 | import { searchBST as bfs } from './solution-bfs'; 34 | testRunner(cases, bfs, 'bfs'); 35 | -------------------------------------------------------------------------------- /js/problems/700.search-in-a-binary-search-tree/solution-bfs.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=700 lang=javascript 3 | * 4 | * [700] Search in a Binary Search Tree 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * Definition for a binary tree node. 10 | * function TreeNode(val) { 11 | * this.val = val; 12 | * this.left = this.right = null; 13 | * } 14 | */ 15 | 16 | interface TreeNode { 17 | val: number; 18 | left: TreeNode | null; 19 | right: TreeNode | null; 20 | } 21 | 22 | /** 23 | * @param {TreeNode} root 24 | * @param {number} val 25 | * @return {TreeNode} 26 | */ 27 | const searchBST = (root: TreeNode | null, val: number): TreeNode | null => { 28 | // * ['72 ms', '92.19 %', '42.7 MB', '6.25 %'] 29 | 30 | if (root === null) return null; 31 | 32 | const queue: TreeNode[] = [root]; 33 | let cur: TreeNode | null = null; 34 | while (queue.length) { 35 | cur = queue.shift()!; 36 | 37 | if (cur.val === val) return cur; 38 | 39 | cur.left && queue.push(cur.left); 40 | cur.right && queue.push(cur.right); 41 | } 42 | 43 | return null; 44 | }; 45 | // @lc code=end 46 | 47 | export { searchBST }; 48 | -------------------------------------------------------------------------------- /js/problems/700.search-in-a-binary-search-tree/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=700 lang=javascript 3 | * 4 | * [700] Search in a Binary Search Tree 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * Definition for a binary tree node. 10 | * function TreeNode(val) { 11 | * this.val = val; 12 | * this.left = this.right = null; 13 | * } 14 | */ 15 | 16 | interface TreeNode { 17 | val: number; 18 | left: TreeNode | null; 19 | right: TreeNode | null; 20 | } 21 | 22 | /** 23 | * @param {TreeNode} root 24 | * @param {number} val 25 | * @return {TreeNode} 26 | */ 27 | const searchBST = (root: TreeNode | null, val: number): TreeNode | null => { 28 | // * ['76 ms', '81.34 %', '42.2 MB', '6.25 %'] 29 | 30 | if (root === null) return null; 31 | 32 | if (root.val === val) return root; 33 | 34 | return searchBST(root.left, val) || searchBST(root.right, val); 35 | }; 36 | // @lc code=end 37 | 38 | export { searchBST }; 39 | -------------------------------------------------------------------------------- /js/problems/704.binary-search/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = [number[], number]; 6 | type Output = number; 7 | 8 | const cases = makeTestCases([ 9 | // 10 | { 11 | input: [[-1, 0, 3, 5, 9, 12], 9], 12 | output: 4, 13 | }, 14 | { 15 | input: [[-1, 0, 3, 5, 9, 12], 2], 16 | output: -1, 17 | }, 18 | 19 | { 20 | input: [[1, 2, 3, 4, 5], -99], 21 | output: -1, 22 | }, 23 | { 24 | input: [[1, 2, 3, 4, 5], 99], 25 | output: -1, 26 | }, 27 | 28 | { 29 | input: [[], 2], 30 | output: -1, 31 | }, 32 | { 33 | input: [[1], 2], 34 | output: -1, 35 | }, 36 | { 37 | input: [[2], 2], 38 | output: 0, 39 | }, 40 | ]); 41 | 42 | // * ------------------------------------------------ 43 | 44 | import { search } from './solution'; 45 | testRunner(cases, search); 46 | -------------------------------------------------------------------------------- /js/problems/704.binary-search/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=704 lang=javascript 3 | * 4 | * [704] Binary Search 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * @param {number[]} nums 10 | * @param {number} target 11 | * @return {number} 12 | */ 13 | const search = (nums: number[], target: number): number => { 14 | // * ['52 ms', '95.49 %', '36.7 MB', '92.86 %'] 15 | let left = 0; 16 | let right = nums.length - 1; 17 | 18 | while (left <= right) { 19 | const mid = ~~((left + right) / 2); 20 | if (target > nums[mid]) { 21 | left = mid + 1; 22 | } else if (target < nums[mid]) { 23 | right = mid - 1; 24 | } else { 25 | return mid; 26 | } 27 | } 28 | 29 | return -1; 30 | }; 31 | // @lc code=end 32 | 33 | export { search }; 34 | -------------------------------------------------------------------------------- /js/problems/707.design-linked-list/types.d.ts: -------------------------------------------------------------------------------- 1 | export interface LinkNode { 2 | val: number; 3 | next: LinkNode | null; 4 | } 5 | 6 | export interface DoublyLinkNode { 7 | val: number; 8 | next: DoublyLinkNode | null; 9 | prev: DoublyLinkNode | null; 10 | } 11 | 12 | export interface MyLinkedListContructor { 13 | new (): MyLinkedListClass; 14 | } 15 | 16 | export interface MyLinkedListClass { 17 | get: (index: number) => number | -1; 18 | addAtHead: (val: number) => void; 19 | addAtTail: (val: number) => void; 20 | addAtIndex: (index: number, val: number) => void; 21 | deleteAtIndex: (index: number) => void; 22 | } 23 | -------------------------------------------------------------------------------- /js/problems/724.find-pivot-index/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = number[]; 6 | type Output = number; 7 | 8 | const cases = makeTestCasesOfSingleInput([ 9 | // 10 | { 11 | input: [1, 7, 3, 6, 5, 6], 12 | output: 3, 13 | }, 14 | { 15 | input: [1, 2, 3], 16 | output: -1, 17 | }, 18 | { 19 | input: [-1, -1, -1, 0, 1, 1], 20 | output: 0, 21 | }, 22 | { 23 | input: [1], 24 | output: 0, 25 | }, 26 | { 27 | input: [], 28 | output: -1, 29 | }, 30 | ]); 31 | 32 | // * ------------------------------------------------ 33 | 34 | import { pivotIndex } from './solution'; 35 | testRunner(cases, pivotIndex); 36 | -------------------------------------------------------------------------------- /js/problems/724.find-pivot-index/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=724 lang=javascript 3 | * 4 | * [724] Find Pivot Index 5 | */ 6 | /** 7 | * @param {number[]} nums 8 | * @return {number} 9 | */ 10 | const pivotIndex = (nums: number[]): number => { 11 | if (nums.length < 1) return -1; 12 | 13 | const halfSum = nums.reduce((a, e) => a + e) / 2; 14 | let leftSum = 0; 15 | for (let i = 0; i < nums.length; i++) { 16 | // * https://leetcode.com/problems/find-pivot-index/discuss/136167/This-is-a-very-poorly-described-problem 17 | // * pivot index is included in both sub-arrays 18 | 19 | leftSum += nums[i]; 20 | if (leftSum === halfSum + nums[i] / 2) return i; 21 | } 22 | 23 | return -1; 24 | }; 25 | 26 | export { pivotIndex }; 27 | -------------------------------------------------------------------------------- /js/problems/733.flood-fill/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = [number[][], number, number, number]; 6 | type Output = number[][]; 7 | 8 | const cases = makeTestCases([ 9 | // 10 | { 11 | input: [ 12 | [ 13 | [1, 1, 1], 14 | [1, 1, 0], 15 | [1, 0, 1], 16 | ], 17 | 1, 18 | 1, 19 | 2, 20 | ], 21 | output: [ 22 | [2, 2, 2], 23 | [2, 2, 0], 24 | [2, 0, 1], 25 | ], 26 | }, 27 | 28 | { 29 | input: [ 30 | [ 31 | [1, 1, 1], 32 | [1, 1, 0], 33 | [1, 0, 1], 34 | ], 35 | 1, 36 | 1, 37 | 1, 38 | ], 39 | output: [ 40 | [1, 1, 1], 41 | [1, 1, 0], 42 | [1, 0, 1], 43 | ], 44 | }, 45 | ]); 46 | 47 | // * ------------------------------------------------ 48 | 49 | import { floodFill } from './solution'; 50 | 51 | testRunner(cases, floodFill); 52 | -------------------------------------------------------------------------------- /js/problems/739.daily-temperatures/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = number[]; 6 | type Output = number[]; 7 | 8 | const cases = makeTestCasesOfSingleInput([ 9 | // 10 | { 11 | input: [73, 74, 75, 71, 69, 72, 76, 73], 12 | output: [1, 1, 4, 2, 1, 1, 0, 0], 13 | }, 14 | { 15 | input: [1, 2, 6, 5, 4, 3, 4, 5, 7, 6, 5], 16 | output: [1, 1, 6, 5, 3, 1, 1, 1, 0, 0, 0], 17 | }, 18 | ]); 19 | 20 | // * ------------------------------------------------ 21 | 22 | import { dailyTemperatures as brute } from './solution-simple'; 23 | import { dailyTemperatures } from './solution'; 24 | testRunner(cases, brute, 'brute'); 25 | testRunner(cases, dailyTemperatures); 26 | -------------------------------------------------------------------------------- /js/problems/739.daily-temperatures/solution-simple.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=739 lang=javascript 3 | * 4 | * [739] Daily Temperatures 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * @param {number[]} T 10 | * @return {number[]} 11 | */ 12 | const dailyTemperatures = (T: number[]): number[] => { 13 | // * brute ['948 ms', '30.97 %', '42.2 MB', '88.89 %'] 14 | 15 | const result: number[] = T.map((e, i) => { 16 | let searchIndex = i; 17 | while (searchIndex <= T.length - 1) { 18 | if (e < T[searchIndex]) return searchIndex - i; 19 | searchIndex++; 20 | } 21 | return 0; 22 | }); 23 | 24 | return result; 25 | }; 26 | // @lc code=end 27 | 28 | export { dailyTemperatures }; 29 | -------------------------------------------------------------------------------- /js/problems/739.daily-temperatures/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=739 lang=javascript 3 | * 4 | * [739] Daily Temperatures 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * @param {number[]} T 10 | * @return {number[]} 11 | */ 12 | const dailyTemperatures = (Temps: number[]): number[] => { 13 | // * helper stack solution ['128 ms', '96.53 %', '42.4 MB', '77.78 %'] 14 | // * https://leetcode-cn.com/problems/daily-temperatures/solution/cheng-xu-yuan-de-zi-wo-xiu-yang-739-daily-temperat/ 15 | 16 | const result: number[] = new Array(Temps.length).fill(0); 17 | const waitingStack: number[] = []; 18 | 19 | const last = (arr: number[]): number => arr[arr.length - 1]; 20 | 21 | for (let curIndex = 0; curIndex < Temps.length; curIndex++) { 22 | const curTemp = Temps[curIndex]; 23 | 24 | while (waitingStack.length && curTemp > Temps[last(waitingStack)]) { 25 | const waitingIndex = waitingStack.pop()!; 26 | result[waitingIndex] = curIndex - waitingIndex; 27 | } 28 | waitingStack.push(curIndex); 29 | } 30 | 31 | return result; 32 | }; 33 | // @lc code=end 34 | 35 | export { dailyTemperatures }; 36 | -------------------------------------------------------------------------------- /js/problems/744.find-smallest-letter-greater-than-target/do.test.ts: -------------------------------------------------------------------------------- 1 | import { LowerLetter } from '../../helper/types'; 2 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 3 | 4 | // * ------------------------------------------------ 5 | 6 | type Char = LowerLetter; 7 | 8 | type Input = [Char[], Char]; 9 | type Output = Char; 10 | 11 | const cases = makeTestCases([ 12 | // 13 | { input: [['c', 'f', 'j'], 'a'], output: 'c' }, 14 | { input: [['c', 'f', 'j'], 'c'], output: 'f' }, 15 | { input: [['c', 'f', 'j'], 'd'], output: 'f' }, 16 | { input: [['c', 'f', 'j'], 'g'], output: 'j' }, 17 | { input: [['c', 'f', 'j'], 'j'], output: 'c' }, 18 | { input: [['c', 'f', 'j'], 'k'], output: 'c' }, 19 | 20 | { input: [['a', 'b'], 'z'], output: 'a' }, 21 | ]); 22 | 23 | // * ------------------------------------------------ 24 | 25 | import { nextGreatestLetter } from './solution'; 26 | testRunner(cases, nextGreatestLetter); 27 | -------------------------------------------------------------------------------- /js/problems/744.find-smallest-letter-greater-than-target/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=744 lang=javascript 3 | * 4 | * [744] Find Smallest Letter Greater Than Target 5 | */ 6 | 7 | import { LowerLetter } from '../../helper/types'; 8 | 9 | // @lc code=start 10 | 11 | type Char = LowerLetter; 12 | 13 | /** 14 | * @param {character[]} letters 15 | * @param {character} target 16 | * @return {character} 17 | */ 18 | const nextGreatestLetter = (letters: Char[], target: Char): Char => { 19 | // * ['60 ms', '82.59 %', '36.2 MB', '100 %'] 20 | 21 | let left = 0; 22 | let right = letters.length - 1; 23 | 24 | while (left < right) { 25 | const mid = ~~((left + right) / 2); 26 | const c = letters[mid]; 27 | if (c <= target) { 28 | left = mid + 1; 29 | } else { 30 | right = mid; 31 | } 32 | } 33 | 34 | return left === right && letters[left] > target ? letters[left] : letters[0]; 35 | }; 36 | // @lc code=end 37 | 38 | export { nextGreatestLetter }; 39 | -------------------------------------------------------------------------------- /js/problems/747.largest-number-at-least-twice-of-others/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = number[]; 6 | type Output = number; 7 | 8 | const cases = makeTestCasesOfSingleInput([ 9 | // 10 | { 11 | input: [3, 6, 1, 0], 12 | output: 1, 13 | }, 14 | { 15 | input: [1, 2, 3, 4], 16 | output: -1, 17 | }, 18 | { 19 | input: [], 20 | output: -1, 21 | }, 22 | ]); 23 | 24 | // * ------------------------------------------------ 25 | 26 | import { dominantIndex } from './solution'; 27 | import { dominantIndex as solution2 } from './solution-2'; 28 | testRunner(cases, dominantIndex); 29 | testRunner(cases, solution2, 'solution2'); 30 | -------------------------------------------------------------------------------- /js/problems/747.largest-number-at-least-twice-of-others/solution-2.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=747 lang=javascript 3 | * 4 | * [747] Largest Number At Least Twice of Others 5 | */ 6 | /** 7 | * @param {number[]} nums 8 | * @return {number} 9 | */ 10 | const dominantIndex = (nums: number[]): number => { 11 | if (nums.length < 1) return -1; 12 | 13 | // * more functional 14 | 15 | const [max, indexOfMax] = nums.reduce( 16 | ([max, indexOfMax], e, i) => (e > max ? [e, i] : [max, indexOfMax]), 17 | [nums[0], 0], 18 | ); 19 | 20 | const matchRule2 = nums.every((e, i) => i == indexOfMax || max >= e * 2); 21 | 22 | return matchRule2 ? indexOfMax : -1; 23 | }; 24 | 25 | export { dominantIndex }; 26 | -------------------------------------------------------------------------------- /js/problems/747.largest-number-at-least-twice-of-others/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=747 lang=javascript 3 | * 4 | * [747] Largest Number At Least Twice of Others 5 | */ 6 | /** 7 | * @param {number[]} nums 8 | * @return {number} 9 | */ 10 | const dominantIndex = (nums: number[]): number => { 11 | if (!nums.length) return -1; 12 | 13 | let max = nums[0], 14 | maxi = 0; 15 | 16 | for (let i = 1; i < nums.length; i++) { 17 | const e = nums[i]; 18 | if (e > max) { 19 | max = e; 20 | maxi = i; 21 | } 22 | } 23 | 24 | for (let i = 0; i < nums.length; i++) { 25 | if (i !== maxi && nums[i] * 2 > max) return -1; 26 | } 27 | 28 | return maxi; 29 | }; 30 | 31 | export { dominantIndex }; 32 | -------------------------------------------------------------------------------- /js/problems/752.open-the-lock/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = [string[], string]; 6 | type Output = number; 7 | 8 | const cases = makeTestCases([ 9 | // 10 | { 11 | input: [['0201', '0101', '0102', '1212', '2002'], '0202'], 12 | output: 6, 13 | }, 14 | { 15 | input: [['8888'], '0009'], 16 | output: 1, 17 | }, 18 | { 19 | input: [['8887', '8889', '8878', '8898', '8788', '8988', '7888', '9888'], '8888'], 20 | output: -1, 21 | }, 22 | { 23 | input: [['0024'], '4444'], 24 | output: 16, 25 | }, 26 | { 27 | input: [['0000'], '8888'], 28 | output: -1, 29 | }, 30 | { 31 | input: [['6666'], '6666'], 32 | output: -1, 33 | }, 34 | { 35 | input: [['0001'], '0000'], 36 | output: 0, 37 | }, 38 | ]); 39 | 40 | // * ------------------------------------------------ 41 | 42 | import { openLock } from './solution'; 43 | import { openLock as fnMid } from './solution-normal'; 44 | import { openLock as fnNaive } from './solution-naive'; 45 | testRunner(cases, openLock); 46 | testRunner(cases, fnMid, 'normal-speed'); 47 | testRunner(cases, fnNaive, 'naive'); 48 | -------------------------------------------------------------------------------- /js/problems/779.k-th-symbol-in-grammar/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = [number, number]; 6 | type Output = number; 7 | 8 | // Explanation: 9 | // row 1: 0 10 | // row 2: 01 11 | // row 3: 0110 12 | // row 4: 01101001 13 | 14 | const cases = makeTestCases([ 15 | // 16 | { input: [1, 1], output: 0 }, 17 | { input: [2, 1], output: 0 }, 18 | { input: [2, 2], output: 1 }, 19 | { input: [4, 5], output: 1 }, 20 | ]); 21 | 22 | // * ------------------------------------------------ 23 | 24 | import { kthGrammar } from './solution'; 25 | import { kthGrammar as fn2 } from './solution-readable'; 26 | testRunner(cases, kthGrammar); 27 | testRunner(cases, fn2, 'fn2'); 28 | -------------------------------------------------------------------------------- /js/problems/779.k-th-symbol-in-grammar/solution-readable.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=779 lang=javascript 3 | * 4 | * [779] K-th Symbol in Grammar 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * @param {number} N 10 | * @param {number} K 11 | * @return {number} 12 | */ 13 | const kthGrammar = (N: number, K: number): number => { 14 | // * ['52 ms', '70.55 %', '33.7 MB', '100 %'] 15 | 16 | if (N === 1) return 0; 17 | 18 | const prev = kthGrammar(N - 1, Math.ceil(K / 2)); 19 | 20 | return map[prev][(K - 1) % 2]; 21 | }; 22 | 23 | const map: Record = { 0: [0, 1], 1: [1, 0] }; 24 | // @lc code=end 25 | 26 | export { kthGrammar }; 27 | -------------------------------------------------------------------------------- /js/problems/779.k-th-symbol-in-grammar/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=779 lang=javascript 3 | * 4 | * [779] K-th Symbol in Grammar 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * @param {number} N 10 | * @param {number} K 11 | * @return {number} 12 | */ 13 | const kthGrammar = (N: number, K: number): number => { 14 | // * ['48 ms', '88.36 %', '33.8 MB', '100 %'] 15 | 16 | if (N === 1) return 0; 17 | 18 | const prev = kthGrammar(N - 1, Math.ceil(K / 2)); 19 | return prev === 0 ? (K % 2 ? 0 : 1) : K % 2 ? 1 : 0; 20 | }; 21 | 22 | // @lc code=end 23 | 24 | export { kthGrammar }; 25 | -------------------------------------------------------------------------------- /js/problems/8.string-to-integer-atoi/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = string; 6 | type Output = number; 7 | 8 | const cases = makeTestCasesOfSingleInput([ 9 | // 10 | 11 | { input: '42', output: 42 }, 12 | { input: ' -42', output: -42 }, 13 | { input: '4193 with words', output: 4193 }, 14 | { input: 'words and 987', output: 0 }, 15 | { input: '-91283472332', output: -2147483648 }, 16 | 17 | { input: '+1', output: 1 }, 18 | ]); 19 | 20 | // * ------------------------------------------------ 21 | 22 | import { myAtoi } from './solution'; 23 | testRunner(cases, myAtoi); 24 | 25 | import { myAtoi as fancy } from './solution-fancy'; 26 | testRunner(cases, fancy, 'fancy'); 27 | -------------------------------------------------------------------------------- /js/problems/8.string-to-integer-atoi/solution-fancy.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=8 lang=javascript 3 | * 4 | * [8] String to Integer (atoi) 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * @param {string} str 10 | * @return {number} 11 | */ 12 | const myAtoi = (str: string): number => { 13 | // * ['72 ms', '84.38 %', '36.1 MB', '57.14 %'] 14 | 15 | const match = str.match(/^\s*[+-]?\d+/); 16 | 17 | if (match === null) return 0; 18 | 19 | const num = Number(match[0].replace(/\s/g, '')); 20 | return Math.max(1 << 31, Math.min(~(1 << 31), num)); 21 | }; 22 | // @lc code=end 23 | 24 | export { myAtoi }; 25 | -------------------------------------------------------------------------------- /js/problems/8.string-to-integer-atoi/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=8 lang=javascript 3 | * 4 | * [8] String to Integer (atoi) 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * @param {string} str 10 | * @return {number} 11 | */ 12 | const myAtoi = (str: string): number => { 13 | // * ['64 ms', '97.6 %', '37.2 MB', '14.29 %'] 14 | 15 | let p = 0; 16 | let sign = 1; 17 | let num = 0; 18 | 19 | while (/\s/.test(str[p])) p++; 20 | 21 | if (str[p] === '-') { 22 | sign = -1; 23 | p++; 24 | } else if (str[p] === '+') { 25 | p++; 26 | } 27 | 28 | if (/\D/.test(str[p])) return 0; 29 | 30 | while (p < str.length) { 31 | if (/\D/.test(str[p])) break; 32 | num = num * 10 + Number(str[p]); 33 | p++; 34 | } 35 | 36 | if (sign < 0) num = -num; 37 | 38 | return Math.max(1 << 31, Math.min(~(1 << 31), num)); 39 | }; 40 | // @lc code=end 41 | 42 | export { myAtoi }; 43 | -------------------------------------------------------------------------------- /js/problems/80.remove-duplicates-from-sorted-array-ii/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = number[]; 6 | type Output = number; 7 | 8 | const cases = makeTestCasesOfSingleInput([ 9 | // 10 | { 11 | input: [1, 1, 1, 2, 2, 3], 12 | output: 5, 13 | }, 14 | { 15 | input: [0, 0, 1, 1, 1, 1, 2, 3, 3], 16 | output: 7, 17 | }, 18 | ]); 19 | 20 | // * ------------------------------------------------ 21 | 22 | import { removeDuplicates } from './solution'; 23 | testRunner(cases, removeDuplicates); 24 | -------------------------------------------------------------------------------- /js/problems/80.remove-duplicates-from-sorted-array-ii/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=80 lang=javascript 3 | * 4 | * [80] Remove Duplicates from Sorted Array II 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * @param {number[]} nums 10 | * @return {number} 11 | */ 12 | const removeDuplicates = (nums: number[]): number => { 13 | // * ['68 ms', '84.38 %', '35.4 MB', '100 %'] 14 | 15 | let newLen = 0; 16 | let lastVal; 17 | let dupCount = 0; 18 | 19 | for (let i = 0; i < nums.length; i++) { 20 | const e = nums[i]; 21 | if (dupCount >= 2 && e === lastVal) continue; 22 | dupCount = e === lastVal ? dupCount + 1 : 1; 23 | nums[newLen] = e; 24 | lastVal = e; 25 | newLen++; 26 | } 27 | 28 | nums.length = newLen; 29 | return newLen; 30 | }; 31 | // @lc code=end 32 | 33 | export { removeDuplicates }; 34 | -------------------------------------------------------------------------------- /js/problems/82.remove-duplicates-from-sorted-list-ii/do.test.ts: -------------------------------------------------------------------------------- 1 | import { ListNode } from '../../structures/linked-list/list-node'; 2 | import { arrayToList } from './../../structures/linked-list/list-to-array'; 3 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 4 | 5 | // * ------------------------------------------------ 6 | 7 | type Input = ListNode | null; 8 | type Output = ListNode | null; 9 | 10 | const a2l = arrayToList; 11 | 12 | const cases = makeTestCasesOfSingleInput([ 13 | // 14 | { 15 | input: a2l([1, 2, 3, 3, 4, 4, 5]), 16 | output: a2l([1, 2, 5]), 17 | }, 18 | { 19 | input: a2l([1, 1, 1, 2, 3]), 20 | output: a2l([2, 3]), 21 | }, 22 | { 23 | input: a2l([1, 1, 1, 2, 2, 2, 3]), 24 | output: a2l([3]), 25 | }, 26 | { 27 | input: a2l([]), 28 | output: a2l([]), 29 | }, 30 | ]); 31 | 32 | // * ------------------------------------------------ 33 | 34 | import { deleteDuplicates } from './solution'; 35 | 36 | testRunner(cases, deleteDuplicates); 37 | -------------------------------------------------------------------------------- /js/problems/83.remove-duplicates-from-sorted-list/do.test.ts: -------------------------------------------------------------------------------- 1 | import { ListNode } from '../../structures/linked-list/list-node'; 2 | import { arrayToList } from './../../structures/linked-list/list-to-array'; 3 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 4 | 5 | // * ------------------------------------------------ 6 | 7 | type Input = ListNode | null; 8 | type Output = ListNode | null; 9 | 10 | const a2l = arrayToList; 11 | 12 | const cases = makeTestCasesOfSingleInput([ 13 | // 14 | { 15 | input: a2l([1, 1, 2]), 16 | output: a2l([1, 2]), 17 | }, 18 | { 19 | input: a2l([1, 1, 2, 3, 3]), 20 | output: a2l([1, 2, 3]), 21 | }, 22 | { 23 | input: a2l([1, 1, 1, 2, 2, 2, 3]), 24 | output: a2l([1, 2, 3]), 25 | }, 26 | { 27 | input: a2l([]), 28 | output: a2l([]), 29 | }, 30 | ]); 31 | 32 | // * ------------------------------------------------ 33 | 34 | import { deleteDuplicates } from './solution'; 35 | 36 | testRunner(cases, deleteDuplicates); 37 | -------------------------------------------------------------------------------- /js/problems/83.remove-duplicates-from-sorted-list/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=83 lang=javascript 3 | * 4 | * [83] Remove Duplicates from Sorted List 5 | */ 6 | 7 | // @lc code=start 8 | 9 | type ListNode = { 10 | val: number; 11 | next: MaybeListNode; 12 | }; 13 | 14 | type MaybeListNode = ListNode | null; 15 | 16 | /** 17 | * Definition for singly-linked list. 18 | * function ListNode(val, next) { 19 | * this.val = (val===undefined ? 0 : val) 20 | * this.next = (next===undefined ? null : next) 21 | * } 22 | */ 23 | /** 24 | * @param {ListNode} head 25 | * @return {ListNode} 26 | */ 27 | const deleteDuplicates = (head: MaybeListNode): MaybeListNode => { 28 | // * ['68 ms', '80.78 %', '35.7 MB', '50.13 %'] 29 | 30 | if (head === null) return head; 31 | 32 | let cur = head; 33 | while (cur.next) { 34 | if (cur.next.val === cur.val) { 35 | cur.next = cur.next.next; 36 | } else { 37 | cur = cur.next; 38 | } 39 | } 40 | 41 | return head; 42 | }; 43 | // @lc code=end 44 | 45 | export { deleteDuplicates }; 46 | -------------------------------------------------------------------------------- /js/problems/841.keys-and-rooms/do.test.ts: -------------------------------------------------------------------------------- 1 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 2 | 3 | // * ------------------------------------------------ 4 | 5 | type Input = number[][]; 6 | type Output = boolean; 7 | 8 | const cases = makeTestCasesOfSingleInput([ 9 | // 10 | { 11 | input: [[1], [2], [3], []], 12 | output: true, 13 | }, 14 | { 15 | input: [[1, 3], [3, 0, 1], [2], [0]], 16 | output: false, 17 | }, 18 | { 19 | input: [[]], 20 | output: true, 21 | }, 22 | { 23 | input: [[1], [1]], 24 | output: true, 25 | }, 26 | ]); 27 | 28 | // * ------------------------------------------------ 29 | 30 | import { canVisitAllRooms } from './solution'; 31 | testRunner(cases, canVisitAllRooms); 32 | -------------------------------------------------------------------------------- /js/problems/841.keys-and-rooms/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=841 lang=javascript 3 | * 4 | * [841] Keys and Rooms 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * @param {number[][]} rooms 10 | * @return {boolean} 11 | */ 12 | const canVisitAllRooms = (rooms: number[][]): boolean => { 13 | // * ['56 ms', '86.69 %', '35.4 MB', '100 %'] 14 | 15 | const keyPool = new Set(); 16 | keyPool.add(0); 17 | 18 | const visited = new Set(); 19 | const checkList: number[] = [0]; 20 | 21 | while (checkList.length) { 22 | const roomNumber = checkList.pop()!; 23 | 24 | if (keyPool.size === rooms.length) break; 25 | 26 | if (!visited.has(roomNumber)) { 27 | visited.add(roomNumber); 28 | const keys = rooms[roomNumber]; 29 | keys.forEach((key) => { 30 | keyPool.add(key); 31 | checkList.push(key); 32 | }); 33 | } 34 | } 35 | 36 | return keyPool.size === rooms.length; 37 | }; 38 | // @lc code=end 39 | 40 | export { canVisitAllRooms }; 41 | -------------------------------------------------------------------------------- /js/problems/94.binary-tree-inorder-traversal/do.test.ts: -------------------------------------------------------------------------------- 1 | import { arrayToTreeWithAutoFix } from './../../structures/tree/tree-to-array'; 2 | import { TreeNode } from './../../structures/tree/tree-node'; 3 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 4 | 5 | // * ------------------------------------------------ 6 | 7 | type Input = TreeNode | null; 8 | type Output = number[]; 9 | 10 | const a2tf = arrayToTreeWithAutoFix; 11 | 12 | const cases = makeTestCasesOfSingleInput([ 13 | // 14 | { 15 | input: a2tf([1, null, 2, 3]), 16 | output: [1, 3, 2], 17 | }, 18 | { 19 | input: a2tf([null]), 20 | output: [], 21 | }, 22 | ]); 23 | 24 | // * ---------------- 25 | 26 | // * ------------------------------------------------ 27 | 28 | import { inorderTraversal as recur } from './solution-recursive'; 29 | import { inorderTraversal as dfs } from './solution'; 30 | testRunner(cases, recur, 'recur'); 31 | testRunner(cases, dfs, 'dfs'); 32 | -------------------------------------------------------------------------------- /js/problems/94.binary-tree-inorder-traversal/solution-recursive.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=94 lang=javascript 3 | * 4 | * [94] Binary Tree Inorder Traversal 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * Definition for a binary tree node. 10 | * function TreeNode(val) { 11 | * this.val = val; 12 | * this.left = this.right = null; 13 | * } 14 | */ 15 | 16 | interface TreeNode { 17 | val: number; 18 | left: TreeNode | null; 19 | right: TreeNode | null; 20 | } 21 | 22 | /** 23 | * @param {TreeNode} root 24 | * @return {number[]} 25 | */ 26 | const inorderTraversal = (root: TreeNode | null): number[] => { 27 | // * simple recursive ['52 ms', '80.34 %', '33.9 MB', '21.88 %'] 28 | const loop = (root: TreeNode | null): number[] => { 29 | if (root === null) return []; 30 | return [...loop(root.left), root.val, ...loop(root.right)]; 31 | }; 32 | 33 | return loop(root); 34 | }; 35 | // @lc code=end 36 | 37 | export { inorderTraversal }; 38 | -------------------------------------------------------------------------------- /js/problems/94.binary-tree-inorder-traversal/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=94 lang=javascript 3 | * 4 | * [94] Binary Tree Inorder Traversal 5 | */ 6 | 7 | // @lc code=start 8 | /** 9 | * Definition for a binary tree node. 10 | * function TreeNode(val) { 11 | * this.val = val; 12 | * this.left = this.right = null; 13 | * } 14 | */ 15 | 16 | interface TreeNode { 17 | val: number; 18 | left: TreeNode | null; 19 | right: TreeNode | null; 20 | } 21 | 22 | /** 23 | * @param {TreeNode} root 24 | * @return {number[]} 25 | */ 26 | const inorderTraversal = (root: TreeNode | null): number[] => { 27 | // * ['52 ms', '80.34 %', '33.7 MB', '87.5 %'] 28 | 29 | const result: number[] = []; 30 | 31 | const dfsWalk = (node: TreeNode | null): void => { 32 | if (node === null) return; 33 | 34 | dfsWalk(node.left); 35 | result.push(node.val); 36 | dfsWalk(node.right); 37 | }; 38 | 39 | dfsWalk(root); 40 | 41 | return result; 42 | }; 43 | // @lc code=end 44 | 45 | export { inorderTraversal }; 46 | -------------------------------------------------------------------------------- /js/problems/95.unique-binary-search-trees-ii/do.test.ts: -------------------------------------------------------------------------------- 1 | import { TreeNode } from './../../structures/tree/tree-node'; 2 | import { arrayToTreeWithAutoFix } from './../../structures/tree/tree-to-array'; 3 | 4 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 5 | 6 | // * ------------------------------------------------ 7 | 8 | type Input = number; 9 | type Output = TreeNode[]; 10 | 11 | const ma2tf = (e: (number | null)[]) => arrayToTreeWithAutoFix(e)!; 12 | 13 | const n = null; 14 | 15 | const cases = makeTestCasesOfSingleInput([ 16 | // 17 | { 18 | input: 3, 19 | output: [ 20 | [1, n, 2, n, n, n, 3], 21 | [1, n, 3, n, n, 2], 22 | [2, 1, 3], 23 | [3, 1, n, n, 2], 24 | [3, 2, n, 1], 25 | ].map(ma2tf), 26 | }, 27 | { 28 | input: 2, 29 | output: [ 30 | [1, null, 2], 31 | [2, 1], 32 | ].map(ma2tf), 33 | }, 34 | { 35 | input: 0, 36 | output: [].map(ma2tf), 37 | }, 38 | ]); 39 | 40 | // * ------------------------------------------------ 41 | 42 | import { generateTrees } from './solution'; 43 | testRunner(cases, generateTrees); 44 | -------------------------------------------------------------------------------- /js/problems/98.validate-binary-search-tree/do.test.ts: -------------------------------------------------------------------------------- 1 | import { TreeNode } from './../../structures/tree/tree-node'; 2 | import { arrayToTree } from './../../structures/tree/tree-to-array'; 3 | import { testRunner, makeTestCases, makeTestCasesOfSingleInput } from '../../helper/test-helper'; 4 | 5 | // * ------------------------------------------------ 6 | 7 | type Input = TreeNode | null; 8 | type Output = boolean; 9 | 10 | const a2t = arrayToTree; 11 | 12 | const cases = makeTestCasesOfSingleInput([ 13 | // 14 | { 15 | input: a2t([2, 1, 3]), 16 | output: true, 17 | }, 18 | { 19 | input: a2t([5, 1, 4, null, null, 3, 6]), 20 | output: false, 21 | }, 22 | 23 | { 24 | input: a2t([1, 1]), 25 | output: false, 26 | }, 27 | 28 | { 29 | input: null, 30 | output: true, 31 | }, 32 | ]); 33 | 34 | // * ------------------------------------------------ 35 | 36 | import { isValidBST as fancy } from './solution-fancy-inorder'; 37 | testRunner(cases, fancy, 'fancy'); 38 | 39 | import { isValidBST as ranger } from './solution-recursion-with-range'; 40 | testRunner(cases, ranger, 'ranger'); 41 | 42 | import { isValidBST } from './solution'; 43 | testRunner(cases, isValidBST); 44 | -------------------------------------------------------------------------------- /js/problems/98.validate-binary-search-tree/solution-fancy-inorder.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=98 lang=javascript 3 | * 4 | * [98] Validate Binary Search Tree 5 | */ 6 | 7 | type MaybeTreeNode = TreeNode | null; 8 | 9 | type TreeNode = { 10 | val: number; 11 | left: MaybeTreeNode; 12 | right: MaybeTreeNode; 13 | }; 14 | 15 | // @lc code=start 16 | /** 17 | * Definition for a binary tree node. 18 | * function TreeNode(val) { 19 | * this.val = val; 20 | * this.left = this.right = null; 21 | * } 22 | */ 23 | /** 24 | * @param {TreeNode} root 25 | * @return {boolean} 26 | */ 27 | const isValidBST = (root: MaybeTreeNode): boolean => { 28 | // * ['208 ms', '5.46 %', '53 MB', '10.26 %'] 29 | 30 | if (root === null) return true; 31 | 32 | return inOrder(root).every((e, i, a) => i === 0 || a[i - 1] < e); 33 | }; 34 | 35 | const inOrder = (root: MaybeTreeNode): number[] => { 36 | if (root === null) return []; 37 | return [...inOrder(root.left), root.val, ...inOrder(root.right)]; 38 | }; 39 | 40 | // @lc code=end 41 | 42 | export { isValidBST }; 43 | -------------------------------------------------------------------------------- /js/problems/98.validate-binary-search-tree/solution-recursion-with-range.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=98 lang=javascript 3 | * 4 | * [98] Validate Binary Search Tree 5 | */ 6 | 7 | type MaybeTreeNode = TreeNode | null; 8 | 9 | type TreeNode = { 10 | val: number; 11 | left: MaybeTreeNode; 12 | right: MaybeTreeNode; 13 | }; 14 | 15 | // @lc code=start 16 | /** 17 | * Definition for a binary tree node. 18 | * function TreeNode(val) { 19 | * this.val = val; 20 | * this.left = this.right = null; 21 | * } 22 | */ 23 | /** 24 | * @param {TreeNode} root 25 | * @return {boolean} 26 | */ 27 | const isValidBST = (root: MaybeTreeNode): boolean => { 28 | // * ['60 ms', '89.11 %', '37.3 MB', '76.92 %'] 29 | 30 | return isBstExt(root, -Infinity, Infinity); 31 | }; 32 | 33 | const isBstExt = (root: MaybeTreeNode, min: number, max: number): boolean => { 34 | if (root === null) return true; 35 | 36 | const mid = root.val; 37 | 38 | if (mid <= min || max <= mid) return false; 39 | 40 | return isBstExt(root.left, min, mid) && isBstExt(root.right, mid, max); 41 | }; 42 | 43 | // @lc code=end 44 | 45 | export { isValidBST }; 46 | -------------------------------------------------------------------------------- /js/problems/98.validate-binary-search-tree/solution.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * @lc app=leetcode id=98 lang=javascript 3 | * 4 | * [98] Validate Binary Search Tree 5 | */ 6 | 7 | type MaybeTreeNode = TreeNode | null; 8 | 9 | type TreeNode = { 10 | val: number; 11 | left: MaybeTreeNode; 12 | right: MaybeTreeNode; 13 | }; 14 | 15 | // @lc code=start 16 | /** 17 | * Definition for a binary tree node. 18 | * function TreeNode(val) { 19 | * this.val = val; 20 | * this.left = this.right = null; 21 | * } 22 | */ 23 | /** 24 | * @param {TreeNode} root 25 | * @return {boolean} 26 | */ 27 | const isValidBST = (root: MaybeTreeNode): boolean => { 28 | // * ['56 ms', '96.7 %', '37.2 MB', '97.44 %'] 29 | 30 | const stack: TreeNode[] = []; 31 | 32 | let lastVal = -Infinity; 33 | 34 | let head = root; 35 | while (head !== null || stack.length > 0) { 36 | while (head !== null) { 37 | stack.push(head); 38 | head = head.left; 39 | } 40 | 41 | head = stack.pop()!; 42 | 43 | if (lastVal >= head.val) return false; 44 | 45 | lastVal = head.val; 46 | head = head.right; 47 | } 48 | 49 | return true; 50 | }; 51 | 52 | // @lc code=end 53 | 54 | export { isValidBST }; 55 | -------------------------------------------------------------------------------- /js/structures/graph/graph-node.ts: -------------------------------------------------------------------------------- 1 | export class GraphNode { 2 | constructor(public val: T, public neighbors: GraphNode[] = []) {} 3 | } 4 | -------------------------------------------------------------------------------- /js/structures/graph/graph-to-array.ts: -------------------------------------------------------------------------------- 1 | import { GraphNode } from './graph-node'; 2 | 3 | type val = number; 4 | 5 | type ArrayList = val[][]; 6 | 7 | export const graphToArray = (node: GraphNode | null): ArrayList => { 8 | if (node === null) return []; 9 | 10 | const visited = new Set(); 11 | const queue: GraphNode[] = [node]; 12 | 13 | const arr: ArrayList = []; 14 | 15 | while (queue.length) { 16 | const node = queue.pop()!; 17 | const { val, neighbors } = node; 18 | 19 | arr[val - 1] = neighbors.map((node) => node.val); 20 | 21 | visited.add(val); 22 | neighbors.forEach((node) => { 23 | if (!visited.has(node.val)) { 24 | queue.push(node); 25 | } 26 | }); 27 | } 28 | 29 | return arr; 30 | }; 31 | 32 | export const arrayToGraph = (arr: ArrayList): GraphNode | null => { 33 | if (arr.length < 1) return null; 34 | 35 | const pool: Record = {}; 36 | 37 | arr.forEach((neighbors, i) => { 38 | const val = i + 1; 39 | const node = new GraphNode(val); 40 | pool[val] = node; 41 | }); 42 | 43 | arr.forEach((neighbors, i) => { 44 | const val = i + 1; 45 | const node = pool[val]; 46 | node.neighbors = neighbors.map((val) => pool[val]); 47 | }); 48 | 49 | return pool[1]; 50 | }; 51 | -------------------------------------------------------------------------------- /js/structures/linked-list/list-node.ts: -------------------------------------------------------------------------------- 1 | export class ListNode { 2 | constructor(public val: T, public next: ListNode | null = null) {} 3 | } 4 | -------------------------------------------------------------------------------- /js/structures/linked-list/list-to-array.test.ts: -------------------------------------------------------------------------------- 1 | import { ListNode } from './list-node'; 2 | import { listToArray, arrayToList } from './list-to-array'; 3 | 4 | describe('null', () => { 5 | test('linkToArray null', () => { 6 | expect(listToArray(null)).toEqual([]); 7 | }); 8 | test('arrayToLink null', () => { 9 | expect(arrayToList([])).toEqual(null); 10 | }); 11 | }); 12 | 13 | describe('normal case', () => { 14 | const l1 = new ListNode(7); 15 | const l2 = new ListNode(11); 16 | const l3 = new ListNode(13); 17 | const l4 = new ListNode(17); 18 | const l5 = new ListNode(23); 19 | 20 | l1.next = l2; 21 | l2.next = l3; 22 | l3.next = l4; 23 | l4.next = l5; 24 | 25 | const arr = [7, 11, 13, 17, 23]; 26 | 27 | test('linkToArray', () => { 28 | expect(listToArray(l1)).toEqual(arr); 29 | }); 30 | 31 | test('arrayToLink', () => { 32 | expect(arrayToList(arr)).toEqual(l1); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /js/structures/linked-list/list-to-array.ts: -------------------------------------------------------------------------------- 1 | import { ListNode } from './list-node'; 2 | type val = any; 3 | 4 | type ArrayList = val[]; 5 | 6 | export const listToArray = (link: ListNode | null): ArrayList => { 7 | const arr = []; 8 | 9 | let cur = link; 10 | while (cur !== null) { 11 | arr.push(cur.val); 12 | cur = cur.next; 13 | } 14 | 15 | return arr; 16 | }; 17 | 18 | export const arrayToList = (arr: ArrayList): ListNode | null => { 19 | const head = new ListNode(null); 20 | 21 | let cur = head; 22 | arr.forEach((e) => { 23 | cur.next = new ListNode(e); 24 | cur = cur.next; 25 | }); 26 | 27 | return head.next; 28 | }; 29 | -------------------------------------------------------------------------------- /js/structures/tree/tree-node.ts: -------------------------------------------------------------------------------- 1 | export class TreeNode { 2 | constructor( 3 | public val: T, 4 | public left: TreeNode | null = null, 5 | public right: TreeNode | null = null, 6 | ) {} 7 | } 8 | -------------------------------------------------------------------------------- /js/tsconfig-build.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES6", 4 | "lib": ["ESNext"], 5 | "module": "CommonJS", 6 | "esModuleInterop": true, 7 | "moduleResolution": "node", 8 | "watch": true 9 | }, 10 | "include": ["problems"], 11 | "exclude": ["node_modules", "**/*.test.*", "**/*.spec.*"] 12 | } 13 | -------------------------------------------------------------------------------- /js/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES6", 4 | "lib": ["ES2020"], 5 | "strict": true, 6 | "esModuleInterop": true, 7 | "moduleResolution": "node" 8 | }, 9 | "include": ["problems", "structures", "helper", "analyze"], 10 | "exclude": ["node_modules"] 11 | } 12 | --------------------------------------------------------------------------------