├── .gitignore ├── .travis.yml ├── LICENSE ├── Makefile ├── README.md ├── bin ├── load └── runTest ├── js ├── 3sum │ └── 3sum.js ├── 3sumClosest │ └── 3sum_closest.js ├── 3sumSmaller │ └── 3sum_smaller.js ├── 4sum │ └── 4sum.js ├── addBinary │ └── add_binary.js ├── addDigits │ └── add_digits.js ├── anagrams │ └── anagrams.js ├── binaryTreeInorderTraversal │ └── binary_tree_inorder_traversal.js ├── binaryTreePaths │ └── binary_tree_paths.js ├── binaryTreePostorderTraversal │ └── binary_tree_postorder_traversal.js ├── binaryTreePreorderTraversal │ └── binary_tree_preorder_traversal.js ├── combinationSum │ ├── README.md │ └── combination-sum.js ├── combinationSumIi │ ├── README.md │ └── combination-sum-ii.js ├── combinationSumIii │ ├── README.md │ └── combination-sum-iii.js ├── combinations │ ├── README.md │ └── combinations.js ├── compareVersionNumbers │ └── compare_version_numbers.js ├── constructBinaryTreeFromInorderAndPostorderTraversal │ └── construct_binary_tree_from_inorder_and_postorder_traversal.js ├── containerWithMostWater │ ├── README.md │ └── container-with-most-water.js ├── containsDuplicate │ └── contains_duplicate.js ├── countAndSay │ └── count_and_say.js ├── deleteNodeInALinkedList │ └── delete_node_in_a_linked_list.js ├── divideTwoIntegers │ └── divide_two_integers.js ├── excelSheetColumnNumber │ └── excel_sheet_column_number.js ├── excelSheetColumnTitle │ └── excel_sheet_column_title.js ├── factorCombinations │ ├── README.md │ └── factor-combinations.js ├── findFirstAndLastPositionOfElementInSortedArray │ ├── README.md │ ├── find-first-and-last-position-of-element-in-sorted-array.js │ └── find-first-and-last-position-of-element-in-sorted-array_1.js ├── findTheDuplicateNumber │ └── find_the_duplicate_number.js ├── firstBadVersion │ └── first_bad_version.js ├── firstMissingPositive │ └── first_missing_positive.js ├── generalizedAbbreviation │ ├── README.md │ └── generalized-abbreviation.js ├── grayCode │ ├── README.md │ └── gray-code.js ├── groupShiftedStrings │ └── group_shifted_strings.js ├── hIndex │ └── h_index.js ├── hIndexIi │ └── h_index_ii.js ├── happyNumber │ └── happy_number.js ├── integerToEnglishWords │ └── integer_to_english_words.js ├── integerToRoman │ └── integer-to-roman.js ├── invertBinaryTree │ └── invert_binary_tree.js ├── isomorphicStrings │ └── isomorphic_strings.js ├── letterCombinationsOfAPhoneNumber │ └── letter_combinations_of_a_phone_number.js ├── linkedListCycleIi │ └── linked_list_cycle_ii.js ├── longestPalindromicSubstring │ └── longest_palindromic_substring.js ├── majorityElement │ └── majority_element.js ├── meetingRooms │ └── meeting_rooms.js ├── mergeSortedArray │ └── merge_sorted_array.js ├── missingNumber │ └── missing_number.js ├── moveZeroes │ └── move_zeroes.js ├── nextPermutation │ ├── README.md │ └── next-permutation.js ├── numberComplement │ ├── README.md │ ├── number-complement-2.js │ └── number-complement.js ├── numberOfDigitOne │ └── number_of_digit_one.js ├── paintFence │ └── paint_fence.js ├── palindromePermutation │ └── palindrome_permutation.js ├── pathSum │ └── path_sum.js ├── perfectSquares │ └── perfect_squares.js ├── permutations │ └── permutations.js ├── permutationsII │ ├── README.md │ └── permutations-ii.js ├── plusOne │ └── plus_one.js ├── powerOfTwo │ └── power_of_two.js ├── powxN │ └── powx_n.js ├── productOfArrayExceptSelf │ └── product_of_array_except_self.js ├── removeDuplicatesFromSortedArray │ └── remove-duplicates-from-sorted-array.js ├── removeDuplicatesFromSortedArrayIi │ └── remove_duplicates_from_sorted_array_ii.js ├── removeDuplicatesFromSortedList │ └── remove_duplicates_from_sorted_list.js ├── removeElement │ └── remove_element.js ├── removeLinkedListElements │ └── remove_linked_list_elements.js ├── restoreIpAddresses │ ├── README.md │ └── restore-ip-addresses.js ├── reverseLinkedList │ └── reverse_linked_list.js ├── reverseString │ └── reverse_string.js ├── reverseVowelsOfAString │ └── reverse_vowels_of_a_string.js ├── reverseWordsInAString │ └── reverse_words_in_a_string.js ├── reverseWordsInAStringIi │ ├── reverse_words_in_a_string_ii-2.js │ └── reverse_words_in_a_string_ii.js ├── romanToInteger │ └── roman-to-integer.js ├── rotateArray │ └── rotate_array.js ├── rotateList │ └── rotate_list.js ├── sameTree │ └── same_tree.js ├── searchInRotatedSortedArray │ └── search_in_rotated_sorted_array.js ├── searchInsertPosition │ └── search_insert_position.js ├── shortestWordDistance │ └── shortest_word_distance.js ├── singleNumber │ └── single_number.js ├── sortColors │ └── sort_colors.js ├── sqrtx │ └── sqrtx.js ├── strobogrammaticNumber │ └── strobogrammatic_number.js ├── strobogrammaticNumberIi │ └── strobogrammatic_number_ii.js ├── subsets │ ├── README.md │ ├── subsets-v1.js │ └── subsets.js ├── sumOfTwoIntegers │ └── sum-of-two-integers.js ├── sumRootToLeafNumbers │ └── sum_root_to_leaf_numbers.js ├── swapNodesInPairs │ └── swap-nodes-in-pairs.js ├── twoSum │ └── two_sum.js ├── twoSumIiInputArrayIsSorted │ └── two_sum_ii_input_array_is_sorted.js ├── twoSumIiiDataStructureDesign │ └── two_sum_iii_data_structure_design.js ├── uglyNumber │ └── ugly_number.js ├── uglyNumberIi │ └── ugly_number_ii.js ├── uniqueWordAbbreviation │ └── unique_word_abbreviation.js ├── validAnagram │ └── valid_anagram.js ├── validPalindrome │ └── valid_palindrome.js ├── validSudoku │ ├── README.md │ └── valid-sudoku.js ├── wordBreak │ └── word_break.js ├── wordPattern │ └── word_pattern.js └── wordSearch │ └── word_search.js ├── package.json ├── python ├── 3sum.py ├── _util.py ├── add_two_numbers.py ├── climbing_stairs.py ├── generate_parentheses.py ├── implement_strstr.py ├── intersection_of_two_linked_lists.py ├── longest_common_prefix.py ├── longest_palindromic_substring.py ├── longest_substring_without_repeating_characters.py ├── lru_cache.py ├── median_of_Two_Sorted_Arrays.py ├── merge_two_sorted_lists.py ├── palindrome_number.py ├── remove_duplicates_from_sorted_array.py ├── remove_nth_node_from_end_of_list.py ├── reverse_integer.py ├── string_to_integer_atoi.py ├── two-sum.py ├── valid_parentheses.py └── zigzag_conversion.py ├── tenth_line.bash ├── valid_phone_numbers.bash └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | # C extensions 6 | *.so 7 | 8 | # Distribution / packaging 9 | .Python 10 | env/ 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | lib/ 17 | lib64/ 18 | parts/ 19 | sdist/ 20 | var/ 21 | *.egg-info/ 22 | .installed.cfg 23 | *.egg 24 | 25 | # PyInstaller 26 | # Usually these files are written by a python script from a template 27 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 28 | *.manifest 29 | *.spec 30 | 31 | # Installer logs 32 | pip-log.txt 33 | pip-delete-this-directory.txt 34 | 35 | # Unit test / coverage reports 36 | htmlcov/ 37 | .tox/ 38 | .coverage 39 | .cache 40 | nosetests.xml 41 | coverage.xml 42 | 43 | # Translations 44 | *.mo 45 | *.pot 46 | 47 | # Django stuff: 48 | *.log 49 | 50 | # Sphinx documentation 51 | docs/_build/ 52 | 53 | # PyBuilder 54 | target/ 55 | node_modules/ 56 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | sudo: false 3 | node_js: 4 | - "12" 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Zhiye Li 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | TESTS = $(shell find js -name '*.js') 3 | 4 | test: 5 | @./bin/runTest $(TESTS) 6 | 7 | .PHONY: test 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # leetcode 2 | 3 | [![Build Status](https://travis-ci.org/zhiyelee/leetcode.svg?branch=master)](https://travis-ci.org/zhiyelee/leetcode) 4 | 5 | Solutions to leetcode in JavaScript and Python. 6 | 7 | ## TEST 8 | 9 | ```js 10 | // install package 11 | npm i 12 | 13 | // run test 14 | npm test 15 | ``` 16 | 17 | ## Tools 18 | 19 | ### Create problem folder 20 | 21 | The folder will include an empty js file and a README file which contains the problem description. 22 | 23 | ``` 24 | yarn 25 | 26 | # pass the problem url as an argument 27 | yarn load https://leetcode.com/problems/combination-sum/ 28 | ``` 29 | 30 | which will create folder `js/combinationSum` with two files. 31 | 32 | ``` 33 | ➜ leetcode git:(master) ✗ tree js/combinationSum 34 | js/combinationSum 35 | ├── README.md # contains problem description and link to the problem 36 | └── combination-sum.js # empty file 37 | ``` 38 | 39 | ## LICENSE 40 | MIT 41 | 42 | -------------------------------------------------------------------------------- /bin/load: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env node 2 | 'use strict'; 3 | const request = require('request'); 4 | const fs = require('fs'); 5 | const camelCase = require('camelcase'); 6 | const mkdirp = require('mkdirp'); 7 | const url = require('url'); 8 | const path = require('path'); 9 | const chalk = require('chalk'); 10 | 11 | const problemUrl = process.argv[3]; 12 | 13 | // problem slug, such as `combination-sum` 14 | const slug = url.parse(problemUrl).pathname.split('/')[2]; 15 | const dirPath = path.resolve('js', camelCase(slug)); 16 | 17 | mkdirp(dirPath, function () { 18 | const fileContent = `## ${slug.replace(/-/g, ' ')}\n` + `link: <${problemUrl}>\n`; 19 | 20 | createFile(path.resolve(dirPath,'README.md'), fileContent); 21 | createFile(path.resolve(dirPath,`${slug}.js`), ''); 22 | }); 23 | 24 | // create file with content only when file is not exists 25 | function createFile(f, content) { 26 | fs.access(f, (err) => { 27 | const relativePath = chalk.green(path.relative(__dirname + '/../', f)); 28 | if (err) { 29 | fs.writeFileSync(f, content); 30 | console.log(`Create:\n\t ${relativePath}`); 31 | return; 32 | } 33 | 34 | console.log(`${chalk.red.bold('File already exists:')}\n\t ${relativePath}`); 35 | }) 36 | } 37 | -------------------------------------------------------------------------------- /bin/runTest: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | export NODE_ENV=test 4 | 5 | echo 6 | for file in $@; do 7 | printf "\033[90m ${file#test/}\033[0m " 8 | node $file 2> /tmp/stderr && echo "\033[36m✓\033[0m" 9 | code=$? 10 | if test $code -ne 0; then 11 | echo "\033[31m✖\033[0m" 12 | cat /tmp/stderr >&2 13 | exit $code 14 | fi 15 | done 16 | echo -------------------------------------------------------------------------------- /js/3sum/3sum.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @return {number[][]} 4 | */ 5 | var threeSum = function(nums) { 6 | nums.sort(function (a, b) { 7 | return a - b; 8 | }); 9 | 10 | var res = []; 11 | var len = nums.length; 12 | 13 | for (var i = 0; i < len - 2; i ++) { 14 | 15 | if (i !== 0 && nums[i] === nums[i - 1]) continue; 16 | var low = i + 1; 17 | var high = len - 1; 18 | var target = -nums[i]; 19 | 20 | while (low < high) { 21 | var val = nums[low] + nums[high]; 22 | if (target === val) { 23 | res.push([nums[i], nums[low ++], nums[high]]); 24 | 25 | // skip repeated value 26 | while (low <= high) { 27 | if (nums[low] > nums[low - 1]) break; 28 | low ++; 29 | } 30 | } else if(val < target) { 31 | low++; 32 | } else { 33 | high --; 34 | } 35 | } 36 | } 37 | 38 | return res; 39 | }; 40 | 41 | var eq = require('assert').deepEqual; 42 | 43 | // return array has same items but maybe different order 44 | eq(threeSum([-1, 0, 1, 2, -1, -4]), [[-1, -1, 2], [-1, 0, 1]]); 45 | eq(threeSum([-2, 0, 1, 1, 2]), [[-2, 0, 2], [-2, 1, 1]]); 46 | 47 | -------------------------------------------------------------------------------- /js/3sumClosest/3sum_closest.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @param {number} target 4 | * @return {number} 5 | */ 6 | var threeSumClosest = function(nums, target) { 7 | // first sort, then use 2sum method 8 | nums.sort(function (a, b) { 9 | return a - b; 10 | }) 11 | 12 | var len = nums.length; 13 | var min = nums[0] + nums[1] + nums[2]; 14 | // suppose length must >= than 3 15 | if (nums.length === 3) return min; 16 | 17 | for (var i = 0; i < len; i++) { 18 | // two pointer, narrow to find the target 19 | var low = i + 1; 20 | var high = len - 1; 21 | 22 | while(low < high) { 23 | var sum = nums[low] + nums[high] + nums[i]; 24 | 25 | if (Math.abs(sum - target) < Math.abs(min - target)) { 26 | min = sum; 27 | if (sum === target) return target; 28 | } 29 | 30 | if(sum < target) { 31 | low += 1; 32 | } else { 33 | high = high - 1; 34 | } 35 | } 36 | } 37 | 38 | return min; 39 | }; 40 | 41 | var eq = require('assert').equal; 42 | 43 | // -4 -1 1 2, 1 44 | eq(threeSumClosest([-1, 2, 1, -4], 1), 2); 45 | eq(threeSumClosest([-1, 2, 1], 4), 2); 46 | eq(threeSumClosest([-1, 2, 1, 1], 1), 1); 47 | eq(threeSumClosest([0,2,1,-3], 1), 0) 48 | -------------------------------------------------------------------------------- /js/3sumSmaller/3sum_smaller.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @param {number} target 4 | * @return {number} 5 | */ 6 | var threeSumSmaller = function(nums, target) { 7 | nums.sort(function(a, b) { 8 | return a - b; 9 | }); 10 | 11 | var len = nums.length; 12 | var ans = 0; 13 | for (var i = 0; i < len; i++) { 14 | var val = nums[i]; 15 | var low = i + 1; 16 | var high = len - 1; 17 | 18 | while(low < high) { 19 | var sum = nums[low] + nums[high]; 20 | if (sum + val < target) { 21 | ans += high - low; 22 | low ++; 23 | } else { 24 | high --; 25 | } 26 | } 27 | } 28 | 29 | return ans; 30 | }; 31 | 32 | 33 | var eq = require('assert').deepEqual; 34 | 35 | eq(threeSumSmaller([-2, 0, 1, 3], 2), 2); 36 | eq(threeSumSmaller([-2, 0, 3], 2), 1); 37 | -------------------------------------------------------------------------------- /js/4sum/4sum.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @param {number} target 4 | * @return {number[][]} 5 | */ 6 | var fourSum = function(nums, target) { 7 | nums.sort(function (a, b) { 8 | return a - b; 9 | }); 10 | 11 | var len = nums.length; 12 | var ans = []; 13 | for (var i = 0; i < len - 3; i++) { 14 | if (i !== 0 && nums[i] === nums[i - 1]) continue; 15 | 16 | for (var j = i + 1; j < len - 2; j ++) { 17 | if (j !== i + 1 && nums[j] === nums[j - 1]) continue; 18 | var find = target - (nums[i] + nums[j]); 19 | var low = j + 1; 20 | var high = len - 1; 21 | 22 | while(low < high) { 23 | var sum = nums[low] + nums[high]; 24 | 25 | if (sum === find) { 26 | ans.push([nums[i], nums[j], nums[low], nums[high]]); 27 | low ++; 28 | 29 | while(low < high) { 30 | if (nums[low] > nums[low - 1]) break; 31 | low ++; 32 | } 33 | 34 | while(low < high) { 35 | if (nums[high - 1] < nums[high]) break; 36 | high --; 37 | } 38 | } 39 | 40 | if (sum < find) { 41 | low ++; 42 | } else { 43 | high --; 44 | } 45 | } 46 | } 47 | } 48 | 49 | return ans; 50 | }; 51 | 52 | var eq = require('assert').deepEqual; 53 | 54 | eq(fourSum([1, 0, -1, 0, -2, 2], 0), [[-2, -1, 1, 2], [-2, 0, 0, 2], [-1, 0, 0, 1]]); 55 | -------------------------------------------------------------------------------- /js/addBinary/add_binary.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} a 3 | * @param {string} b 4 | * @return {string} 5 | */ 6 | var addBinary = function(a, b) { 7 | if (a.length === 0 || b.length === 0) { 8 | return a || b; 9 | } 10 | 11 | var maxL = a.length > b.length ? a.length : b.length; 12 | var carry = 0; 13 | 14 | a = a.split('').reverse(); 15 | b = b.split('').reverse(); 16 | 17 | var sum = []; 18 | 19 | var i = 0; 20 | while (i < maxL) { 21 | var add1 = b[i] || 0; 22 | var add2 = a[i] || 0; 23 | 24 | var tmp = parseInt(add1) + parseInt(add2) + carry; 25 | sum[i] = tmp%2; 26 | carry = tmp >> 1; 27 | i++; 28 | } 29 | 30 | if (carry) { 31 | sum[i] = carry; 32 | } 33 | 34 | return sum.reverse().join(''); 35 | }; 36 | 37 | // test 38 | var assert = require('assert'); 39 | assert.equal(addBinary('10010', '111'), '11001'); 40 | -------------------------------------------------------------------------------- /js/addDigits/add_digits.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number} num 3 | * @return {number} 4 | */ 5 | var addDigits = function(num) { 6 | // https://en.wikipedia.org/wiki/Digital_root 7 | return num ? num - 9 * Math.floor((num - 1)/9) : 0; 8 | 9 | }; 10 | 11 | 12 | var eq = require('assert').equal; 13 | 14 | eq(addDigits(0), 0); 15 | eq(addDigits(18), 9); 16 | eq(addDigits(21), 3); 17 | -------------------------------------------------------------------------------- /js/anagrams/anagrams.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string[]} strs 3 | * @return {string[][]} 4 | */ 5 | var groupAnagrams = function(strs) { 6 | var dicts = {}; 7 | var arrs = []; 8 | 9 | for (var i = 0; i < strs.length; i ++) { 10 | var val = strs[i]; 11 | var key = val.split('').sort().join(''); 12 | 13 | if (dicts[key]) { 14 | dicts[key].push(val); 15 | } else { 16 | arrs.push([val]); 17 | 18 | dicts[key] = arrs[arrs.length - 1]; 19 | } 20 | } 21 | 22 | return arrs; 23 | }; 24 | 25 | 26 | var eq = require('assert').deepEqual; 27 | 28 | // cant test with equal, since this problem doesn't require order inner group 29 | // eq(groupAnagrams(['eat', 'tea', 'tan', 'ate', 'nat', 'bat']), [ 30 | // ['ate', 'eat', 'tea'], 31 | // ['nat', 'tan'], 32 | // ['bat'] 33 | // ]); 34 | -------------------------------------------------------------------------------- /js/binaryTreeInorderTraversal/binary_tree_inorder_traversal.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {TreeNode} root 3 | * @return {number[]} 4 | */ 5 | var inorderTraversal = function(root) { 6 | if (!root) return []; 7 | 8 | var stack = []; 9 | var it; 10 | var ans = []; 11 | it = root; 12 | while(it || stack.length) { 13 | if (it && it.val !== null) { 14 | stack.push(it); 15 | it = it.left; 16 | } else { 17 | var top = stack.pop(); 18 | ans.push(top.val); 19 | it = top.right; 20 | } 21 | } 22 | 23 | return ans; 24 | }; 25 | 26 | var Tree = require('leetcode').Tree; 27 | var eq = require('assert').deepEqual; 28 | 29 | eq(inorderTraversal(Tree.create([1, null, 2, 3])), [1, 3, 2]); 30 | eq(inorderTraversal(Tree.create([1, null, 2, 3, 4, null, 5])), [1, 3, 5, 2, 4]); 31 | -------------------------------------------------------------------------------- /js/binaryTreePaths/binary_tree_paths.js: -------------------------------------------------------------------------------- 1 | // Definition for a binary tree node. 2 | function TreeNode(val) { 3 | this.val = val; 4 | this.left = this.right = null; 5 | } 6 | /** 7 | * @param {TreeNode} root 8 | * @return {string[]} 9 | */ 10 | var binaryTreePaths = function(root) { 11 | if (!root.left && !root.right) return [ root.val.toString() ]; 12 | 13 | var res = []; 14 | getPath(root, res); 15 | 16 | return res; 17 | }; 18 | 19 | function getPath(node, res, pre) { 20 | if (!node) return; 21 | 22 | if (pre === undefined) { 23 | pre = node.val; 24 | } else { 25 | pre = pre + '->' + node.val; 26 | } 27 | 28 | if (!node.left && !node.right) { 29 | return res.push(pre); 30 | } 31 | 32 | getPath(node.left, res, pre); 33 | getPath(node.right, res, pre); 34 | } 35 | 36 | -------------------------------------------------------------------------------- /js/binaryTreePostorderTraversal/binary_tree_postorder_traversal.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {TreeNode} root 3 | * @return {number[]} 4 | */ 5 | var postorderTraversal = function(root) { 6 | if (!root) return []; 7 | 8 | var it = root; 9 | var stack = []; 10 | var ans = []; 11 | 12 | while(it || stack.length) { 13 | if (it && it.val !== null) { 14 | stack.push(it); 15 | it = it.left; 16 | } else { 17 | var top = stack.pop(); 18 | if (top.visited) { 19 | ans.push(top.val); 20 | } else { 21 | top.visited = true; 22 | stack.push(top); 23 | it = top.right; 24 | } 25 | } 26 | } 27 | 28 | return ans; 29 | }; 30 | 31 | // version 2, more directly, same as preodre 32 | var postorderTraversal = function(root) { 33 | if (!root) return []; 34 | 35 | var stack = [root]; 36 | var ans = []; 37 | var it; 38 | 39 | while(stack.length) { 40 | it = stack.pop(); 41 | 42 | if (it.val === null) continue; 43 | ans.unshift(it.val); 44 | 45 | if (it.left) { 46 | stack.push(it.left); 47 | } 48 | 49 | if (it.right) { 50 | stack.push(it.right) 51 | } 52 | } 53 | 54 | return ans; 55 | }; 56 | 57 | var Tree = require('leetcode').Tree; 58 | var eq = require('assert').deepEqual; 59 | 60 | eq(postorderTraversal(Tree.create([1, 2, 3, 4, 5, 6])), [4, 5, 2, 6, 3, 1]); 61 | eq(postorderTraversal(Tree.create([1, null, 2, 3])), [3, 2, 1]); 62 | -------------------------------------------------------------------------------- /js/binaryTreePreorderTraversal/binary_tree_preorder_traversal.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {TreeNode} root 3 | * @return {number[]} 4 | */ 5 | var preorderTraversal = function(root) { 6 | var stack = []; 7 | 8 | if (!root) return []; 9 | 10 | stack.push(root); 11 | 12 | var it; 13 | var ans = []; 14 | while(stack.length) { 15 | it = stack.pop(); 16 | if (it.val === null) continue; 17 | 18 | ans.push(it.val); 19 | 20 | if (it.right) { 21 | stack.push(it.right); 22 | } 23 | if (it.left) { 24 | stack.push(it.left); 25 | } 26 | 27 | } 28 | 29 | return ans; 30 | }; 31 | 32 | var Tree = require('leetcode').Tree; 33 | var eq = require('assert').deepEqual; 34 | 35 | eq(preorderTraversal(Tree.create([1,null,2,3])), [1,2,3]); 36 | eq(preorderTraversal(Tree.create([1,null,2,3,4, null, 5])), [1,2,3, 5, 4]); 37 | 38 | -------------------------------------------------------------------------------- /js/combinationSum/README.md: -------------------------------------------------------------------------------- 1 | ## Combination Sum 2 | link: 3 | 4 | Given a set of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate numbers sums to T. 5 | 6 | 7 | The same repeated number may be chosen from C unlimited number of times. 8 | 9 | 10 | Note: 11 | 12 | All numbers (including target) will be positive integers. 13 | The solution set must not contain duplicate combinations. 14 | 15 | 16 | 17 | 18 | For example, given candidate set [2, 3, 6, 7] and target 7, 19 | A solution set is: 20 | 21 | [ 22 | [7], 23 | [2, 2, 3] 24 | ] 25 | 26 | -------------------------------------------------------------------------------- /js/combinationSum/combination-sum.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} candidates 3 | * @param {number} target 4 | * @return {number[][]} 5 | */ 6 | var combinationSum = function(candidates, target) { 7 | var nums = candidates.sort(function (a, b) { 8 | return a - b; 9 | }) 10 | var result = []; 11 | 12 | getSolution([], nums, target, result); 13 | 14 | return result; 15 | }; 16 | 17 | function getSolution(current, arr, target, result) { 18 | var len = arr.length; 19 | if (arr[0] > target) return; 20 | 21 | for (var i = 0; i < len; i ++) { 22 | var val = arr[i]; 23 | 24 | if (val > target) continue; 25 | 26 | var t = target; 27 | var newCurrent = current; 28 | while (val <= t) { 29 | newCurrent = [].concat(newCurrent, [val]); 30 | 31 | if (val === t) { 32 | result.push(newCurrent); 33 | break; 34 | } 35 | 36 | getSolution(newCurrent, arr.slice(i + 1), t - val, result); 37 | 38 | t = t - val; 39 | } 40 | } 41 | } 42 | 43 | 44 | var eq = require('assert').deepEqual; 45 | eq(combinationSum([2, 3, 6, 7], 7), [ 46 | [2, 2, 3], 47 | [7] 48 | ]); 49 | 50 | // order doesn't matter 51 | eq(combinationSum([48,22,49,24,26,47,33,40,37,39,31,46,36,43,45,34,28,20,29,25,41,32,23], 69), [ 52 | [ 20, 23, 26 ], 53 | [ 20, 24, 25 ], 54 | [ 20, 49 ], 55 | [ 20, 20, 29 ], 56 | [ 22, 23, 24 ], 57 | [ 22, 47 ], 58 | [ 22, 22, 25 ], 59 | [ 23, 46 ], 60 | [ 23, 23, 23 ], 61 | [ 24, 45 ], 62 | [ 26, 43 ], 63 | [ 28, 41 ], 64 | [ 29, 40 ], 65 | [ 32, 37 ], 66 | [ 33, 36 ] 67 | ]); 68 | 69 | -------------------------------------------------------------------------------- /js/combinationSumIi/README.md: -------------------------------------------------------------------------------- 1 | ## Combination Sum II 2 | link: 3 | 4 | Given a collection of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate numbers sums to T. 5 | 6 | 7 | Each number in C may only be used once in the combination. 8 | 9 | Note: 10 | 11 | All numbers (including target) will be positive integers. 12 | The solution set must not contain duplicate combinations. 13 | 14 | 15 | 16 | 17 | For example, given candidate set [10, 1, 2, 7, 6, 1, 5] and target 8, 18 | A solution set is: 19 | 20 | [ 21 | [1, 7], 22 | [1, 2, 5], 23 | [2, 6], 24 | [1, 1, 6] 25 | ] 26 | 27 | -------------------------------------------------------------------------------- /js/combinationSumIi/combination-sum-ii.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} candidates 3 | * @param {number} target 4 | * @return {number[][]} 5 | */ 6 | var combinationSum2 = function(candidates, target) { 7 | const nums = candidates.sort(function (a, b) { 8 | return a - b; 9 | }) 10 | 11 | const result = []; 12 | getSolution([], nums, target, result); 13 | 14 | return result; 15 | }; 16 | 17 | function getSolution(current, arr, target, result) { 18 | 19 | if (arr[0] > target) return; 20 | 21 | const len = arr.length; 22 | var hash = {}; 23 | for (var i = 0; i < len; i++) { 24 | var val = arr[i]; 25 | var newCurrent = [].concat(current, [val]); 26 | 27 | if (val > target) break; 28 | if (hash[val]) continue; 29 | 30 | if (val === target) { 31 | result.push(newCurrent); 32 | } else { 33 | getSolution(newCurrent, arr.slice(i + 1), target - val, result) 34 | } 35 | 36 | hash[val] = 1; 37 | } 38 | } 39 | 40 | 41 | const eq = require('assert').deepEqual; 42 | 43 | eq(combinationSum2([10, 1, 2, 7, 6, 1, 5], 8), [ 44 | [ 1, 1, 6 ], 45 | [ 1, 2, 5 ], 46 | [ 1, 7 ], 47 | [ 2, 6] 48 | ]); 49 | -------------------------------------------------------------------------------- /js/combinationSumIii/README.md: -------------------------------------------------------------------------------- 1 | ## Combination Sum III 2 | link: 3 | 4 | Find all possible combinations of k numbers that add up to a number n, given that only numbers from 1 to 9 can be used and each combination should be a unique set of numbers. 5 | 6 | Example 1: 7 | Input: k = 3, n = 7 8 | 9 | Output: 10 | 11 | > [[1,2,4]] 12 | 13 | 14 | Example 2: 15 | Input: k = 3, n = 9 16 | Output: 17 | > [[1,2,6], [1,3,5], [2,3,4]] 18 | 19 | -------------------------------------------------------------------------------- /js/combinationSumIii/combination-sum-iii.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number} k 3 | * @param {number} n 4 | * @return {number[][]} 5 | */ 6 | var combinationSum3 = function(k, n) { 7 | var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]; 8 | var result = []; 9 | 10 | getSolution([], arr, n, k, result); 11 | 12 | return result; 13 | }; 14 | 15 | function getSolution(current, arr, target, size, result) { 16 | if (size === 1 && (target > 9 || target < arr[0])) return; 17 | 18 | for (var i = 0; i < arr.length; i ++) { 19 | var val = arr[i]; 20 | var newCurrent = [].concat(current, [val]); 21 | if (size === 1) { 22 | if (val === target) { 23 | result.push(newCurrent); 24 | break; 25 | } 26 | continue; 27 | } else { 28 | getSolution(newCurrent, arr.slice(i + 1), target - val, size - 1, result); 29 | } 30 | } 31 | } 32 | 33 | var eq = require('assert').deepEqual; 34 | 35 | eq(combinationSum3(3, 7), [[1, 2, 4]]); 36 | eq(combinationSum3(3, 9), [ 37 | [1, 2, 6], 38 | [1, 3, 5], 39 | [2, 3, 4] 40 | ]); 41 | -------------------------------------------------------------------------------- /js/combinations/README.md: -------------------------------------------------------------------------------- 1 | ## Combinations 2 | link: 3 | 4 | Given two integers n and k, return all possible combinations of k numbers out of 1 ... n. 5 | 6 | For example, 7 | If n = 4 and k = 2, a solution is: 8 | 9 | ``` 10 | [ 11 | [2,4], 12 | [3,4], 13 | [2,3], 14 | [1,2], 15 | [1,3], 16 | [1,4], 17 | ] 18 | 19 | ``` 20 | -------------------------------------------------------------------------------- /js/combinations/combinations.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number} n 3 | * @param {number} k 4 | * @return {number[][]} 5 | */ 6 | var combine = function(n, k) { 7 | 8 | var result = []; 9 | 10 | getSolution([], 1, n, k, result); 11 | return result; 12 | 13 | }; 14 | 15 | function getSolution(current, begin, n, k, result) { 16 | if (k === 0) { 17 | result.push(current); 18 | return; 19 | } 20 | 21 | for (var i = begin; i <= n; i ++) { 22 | 23 | // concat can't pass leetcode test for Time Limit Exceeded, but slice and push can pass 24 | // getSolution([].concat(current, [i]), i + 1, n, k - 1, result); 25 | 26 | var newCurrent = current.slice(0); 27 | newCurrent.push(i); 28 | 29 | getSolution(newCurrent, i + 1, n, k - 1, result); 30 | } 31 | } 32 | 33 | var eq = require('assert').deepEqual; 34 | 35 | eq(combine(4, 2), [ 36 | [1, 2], 37 | [1, 3], 38 | [1, 4], 39 | [2, 3], 40 | [2, 4], 41 | [3, 4], 42 | ]) 43 | -------------------------------------------------------------------------------- /js/compareVersionNumbers/compare_version_numbers.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} version1 3 | * @param {string} version2 4 | * @return {number} 5 | */ 6 | var compareVersion = function(version1, version2) { 7 | var va = version1.split('.').map(function (val) { return parseInt(val, 10); }); 8 | var vb = version2.split('.').map(function (val) { return parseInt(val, 10); }); 9 | 10 | var len = Math.max(va.length, vb.length); 11 | 12 | for (var i = 0; i < len; i ++) { 13 | var sa = i < va.length ? va[i] : 0; 14 | var sb = i < vb.length ? vb[i] : 0; 15 | 16 | if (sa === sb) continue; 17 | 18 | return sa > sb ? 1 : -1; 19 | } 20 | 21 | return 0; 22 | }; 23 | 24 | 25 | var eq = require('assert').equal; 26 | 27 | eq(compareVersion('12.3.11', '1.2.2.2'), 1); 28 | eq(compareVersion('1.1.11', '1.2.0'), -1); 29 | eq(compareVersion('1.1', '1.1'), 0); 30 | eq(compareVersion('0.1', '0.0.1'), 1); 31 | eq(compareVersion('0.1.1', '1.0.1'), -1); 32 | eq(compareVersion('1.0', '1'), 0); 33 | -------------------------------------------------------------------------------- /js/constructBinaryTreeFromInorderAndPostorderTraversal/construct_binary_tree_from_inorder_and_postorder_traversal.js: -------------------------------------------------------------------------------- 1 | var Tree = require('leetcode').Tree; 2 | var TreeNode = Tree.node; 3 | /** 4 | * @param {number[]} inorder 5 | * @param {number[]} postorder 6 | * @return {TreeNode} 7 | */ 8 | var buildTree = function(inorder, postorder) { 9 | // 4 2 1 3 5 10 | // 4 2 5 3 1 11 | // 12 | 13 | var parent = {}; 14 | build(inorder, postorder, parent); 15 | 16 | return parent.next; 17 | }; 18 | 19 | function build(inorder, postorder, parent, type) { 20 | if (!inorder.length || inorder.length !== postorder.length) return null; 21 | 22 | var val = postorder.pop(); 23 | var root = new TreeNode(val); 24 | var idx = inorder.indexOf(val); 25 | if (type) { 26 | parent[type] = root; 27 | } else { 28 | parent.next = root; 29 | } 30 | 31 | 32 | if (!~idx) return null; 33 | 34 | build(inorder.slice(0, idx), postorder.slice(0, idx), root, 'left'); 35 | build(inorder.slice(idx + 1), postorder.slice(idx), root, 'right'); 36 | } 37 | 38 | var eq = require('assert').deepEqual; 39 | 40 | var t1 = buildTree([4, 2, 1, 3, 5], [4, 2, 5, 3, 1]); 41 | var t2 = Tree.create([1, 2, 3, 4, null, null, 5]); 42 | // @todo(zhiye) skip fail test 43 | // console.log(t1, t2) 44 | // eq(t1, t2) 45 | -------------------------------------------------------------------------------- /js/containerWithMostWater/README.md: -------------------------------------------------------------------------------- 1 | ## Container With Most Water 2 | link: 3 | 4 | Given n non-negative integers a1, a2, ..., an , where each represents a point at coordinate (i, ai). n vertical lines are drawn such that the two endpoints of the line i is at (i, ai) and (i, 0). Find two lines, which, together with the x-axis forms a container, such that the container contains the most water. 5 | 6 | Notice that you may not slant the container. 7 | 8 | 9 | 10 | Example 1: 11 | ![img](https://s3-lc-upload.s3.amazonaws.com/uploads/2018/07/17/question_11.jpg) 12 | 13 | ``` 14 | Input: height = [1,8,6,2,5,4,8,3,7] 15 | Output: 49 16 | ``` 17 | Explanation: The above vertical lines are represented by array [1,8,6,2,5,4,8,3,7]. In this case, the max area of water (blue section) the container can contain is 49. 18 | Example 2: 19 | 20 | ``` 21 | Input: height = [1,1] 22 | Output: 1 23 | ``` 24 | Example 3: 25 | 26 | ``` 27 | Input: height = [4,3,2,1,4] 28 | Output: 16 29 | ``` 30 | 31 | Example 4: 32 | 33 | ``` 34 | Input: height = [1,2,1] 35 | Output: 2 36 | ``` 37 | 38 | 39 | Constraints: 40 | 41 | - n == height.length 42 | - 2 <= n <= 105 43 | - 0 <= height[i] <= 104 44 | -------------------------------------------------------------------------------- /js/containerWithMostWater/container-with-most-water.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} height 3 | * @return {number} 4 | */ 5 | var maxArea = function(height) { 6 | let max = 0; 7 | const length = height.length; 8 | for (let left = 0; left < length - 1; left ++) { 9 | for (let right = length - 1; right > left; right --) { 10 | const area = (right - left) * Math.min(height[left], height[right]); 11 | if (area > max) max = area; 12 | 13 | if (height[right] >= height[left]) break; 14 | } 15 | } 16 | 17 | return max; 18 | }; 19 | 20 | 21 | var eq = require('assert').strictEqual; 22 | eq(maxArea([4,3,2,1,4]), 16); 23 | eq(maxArea([1,8,6,2,5,4,8,3,7]), 49); 24 | eq(maxArea([1,8,6,2,5,4,8,3,7]), 49); 25 | 26 | -------------------------------------------------------------------------------- /js/containsDuplicate/contains_duplicate.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @return {boolean} 4 | */ 5 | // use some 6 | var containsDuplicate = function(nums) { 7 | var hash = {}; 8 | 9 | return nums.some(function (val) { 10 | if (hash[val]) return true; 11 | hash[val] = 1; 12 | }); 13 | }; 14 | 15 | var containsDuplicate = function(nums) { 16 | return nums.length > (new Set(nums)).size; 17 | }; 18 | 19 | 20 | var eq = require('assert').equal; 21 | 22 | eq(containsDuplicate([1,2,3]), false); 23 | eq(containsDuplicate([1,2,1]), true); 24 | eq(containsDuplicate([]), false); 25 | -------------------------------------------------------------------------------- /js/countAndSay/count_and_say.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number} n 3 | * @return {string} 4 | */ 5 | var countAndSay = function(n) { 6 | var m = '1'; 7 | for (var i = 0; i < n - 1; i ++) { 8 | m = f(m); 9 | } 10 | 11 | return m; 12 | }; 13 | 14 | 15 | function f(n) { 16 | n = n.toString(); 17 | var res = ''; 18 | var count = 0; 19 | var pre = ''; 20 | 21 | if (n == 1) return '11'; 22 | for (var i = 0; i < n.length; i ++) { 23 | if (pre === n.charAt(i)) { 24 | count += 1; 25 | } else { 26 | res += count ? `${count}${pre}` : ''; 27 | pre = n.charAt(i); 28 | count = 1; 29 | } 30 | } 31 | 32 | res += `${count}${pre}`; 33 | return res; 34 | } 35 | 36 | 37 | var eq = require('assert').equal; 38 | 39 | eq(countAndSay(1), '1'); 40 | eq(countAndSay(4), '1211'); 41 | eq(countAndSay(5), '111221'); 42 | -------------------------------------------------------------------------------- /js/deleteNodeInALinkedList/delete_node_in_a_linked_list.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * function ListNode(val) { 4 | * this.val = val; 5 | * this.next = null; 6 | * } 7 | */ 8 | /** 9 | * @param {ListNode} node 10 | * @return {void} Do not return anything, modify node in-place instead. 11 | */ 12 | var deleteNode = function(node) { 13 | var current = node; 14 | var slow = {}; 15 | 16 | while(current.next) { 17 | var next = current.next; 18 | current.val = next.val; 19 | slow = current; 20 | current = next; 21 | } 22 | 23 | slow.next = null; 24 | }; 25 | -------------------------------------------------------------------------------- /js/divideTwoIntegers/divide_two_integers.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number} dividend 3 | * @param {number} divisor 4 | * @return {number} 5 | */ 6 | var divide = function(dividend, divisor) { 7 | if (!divisor) return +Infinity; 8 | var sign = (dividend < 0) ^ (divisor < 0) ? -1 : 1; 9 | 10 | dividend = Math.abs(dividend); 11 | divisor = Math.abs(divisor); 12 | 13 | if (divisor === 1) return !~sign ? -dividend: dividend; 14 | 15 | var res; 16 | var sum = 0; 17 | while (dividend >= divisor) { 18 | var val = divisor; 19 | var ans = 1; 20 | // val << 1 may overflow to negative 21 | while (dividend >= (val << 1) && (val << 1) > 0) { 22 | val <<= 1; 23 | ans <<= 1; 24 | } 25 | 26 | dividend -= val; 27 | sum += ans; 28 | } 29 | 30 | if (!~sign) sum = -sum; 31 | return sum; 32 | }; 33 | 34 | 35 | var eq = require('assert').equal; 36 | 37 | eq(divide(18, 2), 9); 38 | eq(divide(32, -2), -16); 39 | eq(divide(2147483647, 2), 1073741823); 40 | -------------------------------------------------------------------------------- /js/excelSheetColumnNumber/excel_sheet_column_number.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} s 3 | * @return {number} 4 | */ 5 | var titleToNumber = function(s) { 6 | return s.split('') 7 | .reverse() 8 | .reduce(function (pre, item, i) { 9 | item = item.charCodeAt(0) - 64; 10 | return pre + item * Math.pow(26, i); 11 | }, 0); 12 | }; 13 | 14 | var eq = require('assert').equal; 15 | 16 | eq(titleToNumber('Z'), 26); 17 | eq(titleToNumber('AB'), 28); 18 | eq(titleToNumber('AA'), 27); 19 | eq(titleToNumber('AAA'), 703); 20 | -------------------------------------------------------------------------------- /js/excelSheetColumnTitle/excel_sheet_column_title.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number} n 3 | * @return {string} 4 | */ 5 | var convertToTitle = function(n) { 6 | // A unicode value 65 7 | var s = 65; 8 | var ans = ''; 9 | while (n) { 10 | n -= 1; 11 | var tmp = String.fromCharCode(s + n % 26) 12 | ans = tmp + ans; 13 | 14 | n = Math.floor(n / 26); 15 | } 16 | 17 | return ans; 18 | }; 19 | 20 | 21 | var eq = require('assert').equal; 22 | 23 | eq(convertToTitle(27), 'AA') 24 | eq(convertToTitle(26), 'Z') 25 | eq(convertToTitle(703), 'AAA') 26 | -------------------------------------------------------------------------------- /js/factorCombinations/README.md: -------------------------------------------------------------------------------- 1 | ## Factor Combinations 2 | link: 3 | 4 | Numbers can be regarded as product of its factors. For example, 5 | 6 | ``` 7 | 8 = 2 x 2 x 2; 8 | = 2 x 4. 9 | ``` 10 | 11 | Write a function that takes an integer n and return all possible combinations of its factors. 12 | 13 | 14 | Note: 15 | 16 | You may assume that n is always positive. 17 | Factors should be greater than 1 and less than n. 18 | 19 | 20 | Examples: 21 | input: 1 22 | output: 23 | 24 | ``` 25 | [] 26 | ``` 27 | 28 | input: 37 29 | output: 30 | 31 | [] 32 | 33 | input: 12 34 | output: 35 | 36 | ``` 37 | [ 38 | [2, 6], 39 | [2, 2, 3], 40 | [3, 4] 41 | ] 42 | ``` 43 | 44 | input: 32 45 | output: 46 | 47 | ``` 48 | [ 49 | [2, 16], 50 | [2, 2, 8], 51 | [2, 2, 2, 4], 52 | [2, 2, 2, 2, 2], 53 | [2, 4, 4], 54 | [4, 8] 55 | ] 56 | ``` 57 | 58 | -------------------------------------------------------------------------------- /js/factorCombinations/factor-combinations.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number} n 3 | * @return {number[][]} 4 | */ 5 | var getFactors = function(n) { 6 | var result = []; 7 | 8 | getSolutions([], 2, n, result); 9 | 10 | return result; 11 | }; 12 | 13 | function getSolutions(current, begin, n, result) { 14 | // when target is not integer 15 | if (parseInt(n, 10) !== n) return; 16 | 17 | // instead of `i < n`, reduce complexity to logn 18 | for (var i = begin; i <= Math.sqrt(n); i ++) { 19 | var target = n; 20 | var val = i; 21 | var newCurrent = current; 22 | 23 | // in case of duplicate 24 | while(target > val) { 25 | var left = target % val; 26 | target = target / val; 27 | 28 | if (left !== 0 || target < val) break; 29 | 30 | newCurrent = newCurrent.slice(0).concat([i]); 31 | // only push `target` to result if target >= val 32 | result.push(newCurrent.slice(0).concat([target])); 33 | getSolutions(newCurrent, i + 1, target, result); 34 | } 35 | } 36 | } 37 | 38 | 39 | var eq = require('assert').deepEqual; 40 | 41 | eq(getFactors(1), []); 42 | eq(getFactors(3), []); 43 | eq(getFactors(32), [ 44 | [ 2, 16 ], 45 | [ 2, 4, 4 ], 46 | [ 2, 2, 8 ], 47 | [ 2, 2, 2, 4 ], 48 | [ 2, 2, 2, 2, 2 ], 49 | [ 4, 8 ], 50 | ]); 51 | -------------------------------------------------------------------------------- /js/findFirstAndLastPositionOfElementInSortedArray/README.md: -------------------------------------------------------------------------------- 1 | ## find first and last position of element in sorted array 2 | link: 3 | -------------------------------------------------------------------------------- /js/findFirstAndLastPositionOfElementInSortedArray/find-first-and-last-position-of-element-in-sorted-array.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @param {number} target 4 | * @return {number[]} 5 | */ 6 | var searchRange = function(nums, target) { 7 | let left = -1; 8 | let right = -1; 9 | let low = 0; 10 | let high = nums.length - 1; 11 | 12 | while (low <= high) { 13 | const mid = Math.floor((high + low) / 2); 14 | const midValue = nums[mid]; 15 | if(midValue === target) { 16 | right = left = mid; 17 | 18 | // this approach is easier to understand 19 | // go all the way right until see a non-target value 20 | let i = mid + 1; 21 | while (i <= high && nums[i] === target) { 22 | right = i; 23 | i ++; 24 | } 25 | 26 | // go all the way left until see a non-target value 27 | let j = mid - 1; 28 | while(j >= low && nums[j] === target) { 29 | left = j; 30 | j --; 31 | } 32 | 33 | break; 34 | } 35 | 36 | if (midValue < target) low = mid + 1; 37 | if (midValue > target) high = mid - 1; 38 | } 39 | 40 | return [left, right]; 41 | }; 42 | 43 | const eq = require('assert').deepStrictEqual 44 | 45 | eq(searchRange([5, 6, 7, 7, 8, 8, 8, 10], 8), [4, 6]); 46 | eq(searchRange([5,7,7,8,8,10], 8), [3, 4]); 47 | eq(searchRange([5,7,7,8,8,10], 6), [-1, -1]); 48 | eq(searchRange([], 0), [-1, -1]); 49 | -------------------------------------------------------------------------------- /js/findFirstAndLastPositionOfElementInSortedArray/find-first-and-last-position-of-element-in-sorted-array_1.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @param {number} target 4 | * @return {number[]} 5 | */ 6 | var searchRange = function(nums, target) { 7 | let left = -1; 8 | let right = -1; 9 | let low = 0; 10 | let high = nums.length - 1; 11 | 12 | while (low <= high) { 13 | const mid = Math.floor((high + low) / 2); 14 | const midValue = nums[mid]; 15 | if(midValue === target) { 16 | right = left = mid; 17 | const [hightLeft, highRight] = searchRange(nums.slice(mid + 1), target); 18 | const [lowLeft, lowRight] = searchRange(nums.slice(low, mid), target); 19 | 20 | if (highRight >= 0) right = mid + 1 + highRight; 21 | if (lowLeft >= 0) left = low + lowLeft; 22 | break; 23 | } 24 | 25 | if (midValue < target) low = mid + 1; 26 | if (midValue > target) high = mid - 1; 27 | } 28 | 29 | return [left, right]; 30 | }; 31 | 32 | const eq = require('assert').deepStrictEqual 33 | 34 | eq(searchRange([5, 6, 7, 7, 8, 8, 8, 10], 8), [4, 6]); 35 | eq(searchRange([5,7,7,8,8,10], 8), [3, 4]); 36 | eq(searchRange([5,7,7,8,8,10], 6), [-1, -1]); 37 | eq(searchRange([], 0), [-1, -1]); 38 | -------------------------------------------------------------------------------- /js/findTheDuplicateNumber/find_the_duplicate_number.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @return {number} 4 | */ 5 | var findDuplicate = function(nums) { 6 | // 1 2 3 3 4 7 | // 1 3 3 3 3 8 | // solution http://keithschwarz.com/interesting/code/?dir=find-duplicate 9 | var len = nums.length; 10 | 11 | var slow = len -1; 12 | var fast = len - 1; 13 | while(true) { 14 | slow = nums[slow] - 1; 15 | fast = nums[nums[fast] - 1] - 1; 16 | 17 | if (slow === fast) { 18 | break; 19 | } 20 | } 21 | 22 | var finder = len - 1; 23 | while(true) { 24 | slow = nums[slow] - 1; 25 | finder = nums[finder] - 1; 26 | 27 | if (slow === finder) { 28 | return finder + 1; 29 | } 30 | } 31 | }; 32 | 33 | 34 | var eq = require('assert').equal; 35 | 36 | eq(findDuplicate([1, 2, 3, 3, 4]), 3); 37 | eq(findDuplicate([2, 1, 1]), 1); 38 | -------------------------------------------------------------------------------- /js/firstBadVersion/first_bad_version.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for isBadVersion() 3 | * 4 | * @param {integer} version number 5 | * @return {boolean} whether the version is bad 6 | * isBadVersion = function(version) { 7 | * ... 8 | * }; 9 | */ 10 | 11 | /** 12 | * @param {function} isBadVersion() 13 | * @return {function} 14 | */ 15 | var solution = function(isBadVersion) { 16 | /** 17 | * @param {integer} n Total versions 18 | * @return {integer} The first bad version 19 | */ 20 | return function(n) { 21 | var low = 1; 22 | var high = n; 23 | 24 | var mid; 25 | while(low < high) { 26 | mid = low + ((high -low) >> 1); 27 | if (isBadVersion(mid)) { 28 | high = mid; 29 | } else { 30 | low = mid + 1; 31 | } 32 | } 33 | 34 | return low; 35 | }; 36 | }; 37 | -------------------------------------------------------------------------------- /js/firstMissingPositive/first_missing_positive.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @return {number} 4 | */ 5 | 'use strict'; 6 | var firstMissingPositive = function(nums) { 7 | var len = nums.length; 8 | if (len === 0) return 1; 9 | 10 | for (var i = 0; i < nums.length; i++) { 11 | var val = nums[i]; 12 | var tmp; 13 | if (val <= 0 || val > len || val === nums[val - 1]) { 14 | continue; 15 | } 16 | 17 | if (i !== val - 1) { 18 | tmp = val; 19 | nums[i] = nums[val - 1]; 20 | nums[val - 1] = val; 21 | i--; 22 | } 23 | } 24 | for (var idx = 0; idx < len; idx++) { 25 | if (idx !== nums[idx] - 1) { 26 | return idx + 1; 27 | } 28 | } 29 | 30 | return len + 1 31 | }; 32 | 33 | var assert = require('assert'); 34 | 35 | var a = [0]; 36 | assert.equal(firstMissingPositive(a), 1) 37 | a = [1]; 38 | assert.equal(firstMissingPositive(a), 2) 39 | 40 | a = [1, 2, 0]; 41 | assert.equal(firstMissingPositive(a), 3) 42 | 43 | a = [3,4,-1,1]; 44 | assert.equal(firstMissingPositive(a), 2) 45 | 46 | -------------------------------------------------------------------------------- /js/generalizedAbbreviation/README.md: -------------------------------------------------------------------------------- 1 | ## 320. Generalized Abbreviation 2 | link: 3 | 4 | Write a function to generate the generalized abbreviations of a word. 5 | 6 | Example: 7 | Given word = "word", return the following list (order does not matter): 8 | 9 | > ["word", "1ord", "w1rd", "wo1d", "wor1", "2rd", "w2d", "wo2", "1o1d", "1or1", "w1r1", "1o2", "2r1", "3d", "w3", "4"] 10 | -------------------------------------------------------------------------------- /js/generalizedAbbreviation/generalized-abbreviation.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} word 3 | * @return {string[]} 4 | */ 5 | var generateAbbreviations = function(word) { 6 | var result = []; 7 | getSolutions('', word, result); 8 | return result; 9 | }; 10 | 11 | function getSolutions(current, str, result) { 12 | if (str.length === 0) { 13 | result.push(current); 14 | return; 15 | } 16 | 17 | // add first char without converting 18 | getSolutions(current + str.charAt(0), str.substr(1), result); 19 | 20 | // can't produce continuous numbers in the result 21 | var lastChar = current.substr(-1); 22 | if (lastChar && /[0-9]/.test(lastChar)) return; 23 | 24 | for (var i = 1; i <= str.length; i ++) { 25 | var val = str.substr(0, i); 26 | getSolutions(current + i, str.substr(i), result); 27 | } 28 | } 29 | 30 | var eq = require('assert').deepEqual; 31 | eq(generateAbbreviations('word'), [ 32 | 'word', 33 | 'wor1', 34 | 'wo1d', 35 | 'wo2', 36 | 'w1rd', 37 | 'w1r1', 38 | 'w2d', 39 | 'w3', 40 | '1ord', 41 | '1or1', 42 | '1o1d', 43 | '1o2', 44 | '2rd', 45 | '2r1', 46 | '3d', 47 | '4' 48 | ]); 49 | -------------------------------------------------------------------------------- /js/grayCode/README.md: -------------------------------------------------------------------------------- 1 | ## Gray Code 2 | link: 3 | The gray code is a binary numeral system where two successive values differ in only one bit. 4 | 5 | Given a non-negative integer n representing the total number of bits in the code, print the sequence of gray code. A gray code sequence must begin with 0. 6 | 7 | For example, given n = 2, return [0,1,3,2]. Its gray code sequence is: 8 | 9 | 00 - 0 10 | 01 - 1 11 | 11 - 3 12 | 10 - 2 13 | 14 | 15 | Note: 16 | For a given n, a gray code sequence is not uniquely defined. 17 | 18 | For example, [0,2,3,1] is also a valid gray code sequence according to the above definition. 19 | 20 | For now, the judge is able to judge based on one instance of gray code sequence. Sorry about that. -------------------------------------------------------------------------------- /js/grayCode/gray-code.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number} n 3 | * @return {number[]} 4 | * @note solution see https://is.gd/MiDHHf 5 | */ 6 | var grayCode = function(n) { 7 | var res = []; 8 | res.push(0); 9 | for (var i = 0; i < n; i++) { 10 | var size = res.length; 11 | 12 | for (var k = size - 1; k >= 0; k --) { 13 | res.push(res[k] | 1 << i) 14 | } 15 | } 16 | 17 | return res; 18 | }; 19 | 20 | var eq = require('assert').deepEqual; 21 | 22 | eq(grayCode(3), [ 0, 1, 3, 2, 6, 7, 5, 4 ]); 23 | eq(grayCode(2), [ 0, 1, 3, 2 ]); 24 | -------------------------------------------------------------------------------- /js/groupShiftedStrings/group_shifted_strings.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string[]} strings 3 | * @return {string[][]} 4 | */ 5 | var groupStrings = function(strings) { 6 | var dicts = {}; 7 | var gs = []; 8 | 9 | for (var i = 0; i < strings.length; i ++) { 10 | var val = strings[i]; 11 | var key = getKey(val); 12 | 13 | if (dicts[key]) { 14 | dicts[key].push(val); 15 | } else { 16 | gs.push([val]); 17 | dicts[key] = gs[gs.length - 1]; 18 | } 19 | } 20 | 21 | return gs; 22 | }; 23 | 24 | // encode string with distance of two adjacent charactors, 25 | // return `-11-2` etc 26 | function getKey(str) { 27 | var key = ''; 28 | for(var i = 1; i < str.length; i ++) { 29 | var val = str.charCodeAt(i); 30 | var preVal = str.charCodeAt(i - i); 31 | 32 | var d = val - preVal; 33 | if (val < preVal) { 34 | d = val - preVal + 26; 35 | } 36 | 37 | // distance could be `11`, need to distinguish with `'1'` + `'1'` 38 | key += '-' + d; 39 | } 40 | 41 | return key; 42 | } 43 | 44 | var eq = require('assert').deepEqual; 45 | 46 | // @note this problem doesn't require the order of groups 47 | eq(groupStrings(['abc', 'bcd', 'acef', 'xyz', 'az', 'ba', 'a', 'z']), [ 48 | ['abc','bcd','xyz'], 49 | ['acef'], 50 | ['az','ba'], 51 | ['a','z'] 52 | ]); 53 | 54 | eq(groupStrings(['abc','am']), [ 55 | ['abc'], 56 | ['am'] 57 | ]); 58 | -------------------------------------------------------------------------------- /js/hIndex/h_index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} citations 3 | * @return {number} 4 | */ 5 | // var hIndex = function(citations) { 6 | // if (!citations.length) return 0; 7 | // citations = citations.sort(function (a, b) { 8 | // return b - a; 9 | // }); 10 | // 11 | // var pre = citations[0]; 12 | // var h = Math.min(pre, 1); 13 | // # dummy node at the end 14 | // citations.push(-1); 15 | // 16 | // for (var i = 1; i < citations.length; i++) { 17 | // var val = citations[i]; 18 | // 19 | // if (pre >= i) { 20 | // h = i; 21 | // } 22 | // pre = val; 23 | // } 24 | // 25 | // return h; 26 | // }; 27 | 28 | // hash solution 29 | var hIndex = function(citations) { 30 | var possible = []; 31 | var len = citations.length; 32 | if (len === 0) return 0; 33 | 34 | // possible array length = citations.length + 1, 0 - citations.length 35 | possible.length = len + 2; 36 | // fill with 0 37 | possible = possible.join('-').split('').map(function() { 38 | return 0; 39 | }); 40 | 41 | for (var i = 0; i < len; i ++) { 42 | var val = citations[i]; 43 | var idx = val > len ? len : val; 44 | 45 | possible[idx] += 1; 46 | } 47 | 48 | var result = 0; 49 | for (var k = len; k >= 0; k --) { 50 | result += possible[k]; 51 | if (result >= k) { 52 | return k; 53 | } 54 | } 55 | } 56 | 57 | var eq = require('assert').equal; 58 | 59 | eq(hIndex([]), 0); 60 | eq(hIndex([0]), 0); 61 | eq(hIndex([2, 2, 2]), 2); 62 | eq(hIndex([3, 0, 6, 1, 5]), 3); 63 | eq(hIndex([5, 4, 6, 1, 5]), 4); 64 | eq(hIndex([5, 6]), 2); 65 | -------------------------------------------------------------------------------- /js/hIndexIi/h_index_ii.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} citations 3 | * @return {number} 4 | */ 5 | var hIndex = function(citations) { 6 | var len = citations.length; 7 | 8 | citations.unshift(0); 9 | var low = 0; 10 | var high = len; 11 | var mid; 12 | var max = 0; 13 | while (low <= high) { 14 | mid = (low + high) >> 1; 15 | 16 | // numbers count >= citations[mid] 17 | var largetLeft = len - mid + 1; 18 | if (citations[mid] >= largetLeft) { 19 | max = Math.max(max, largetLeft); 20 | high = mid - 1; 21 | } else { 22 | low = mid + 1; 23 | } 24 | } 25 | 26 | return max; 27 | }; 28 | 29 | var eq = require('assert').equal; 30 | 31 | eq(hIndex([]), 0); 32 | eq(hIndex([0]), 0); 33 | eq(hIndex([2, 2, 2]), 2); 34 | eq(hIndex([0, 1, 3, 5, 6]), 3); 35 | eq(hIndex([1, 4, 5, 5, 6]), 4); 36 | -------------------------------------------------------------------------------- /js/happyNumber/happy_number.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number} n 3 | * @return {boolean} 4 | */ 5 | var isHappy = function(n) { 6 | var mem = []; 7 | 8 | while (true) { 9 | var arr = n.toString().split(''); 10 | 11 | n = arr.reduce(function (pre, current) { 12 | current = parseInt(current); 13 | return pre + current * current; 14 | }, 0); 15 | 16 | if (n === 1) return true; 17 | if (mem.indexOf(n) !== -1) { 18 | return false; 19 | } 20 | 21 | mem.push(n); 22 | } 23 | }; 24 | 25 | 26 | var eq = require('assert').equal; 27 | 28 | eq(isHappy(19), true); 29 | eq(isHappy(18), false); 30 | -------------------------------------------------------------------------------- /js/integerToEnglishWords/integer_to_english_words.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number} num 3 | * @return {string} 4 | */ 5 | var numberToWords = function(num) { 6 | var quantityHash = ['', 'Thousand', 'Million', 'Billion']; 7 | 8 | if (num === 0) return 'Zero'; 9 | 10 | // separate num into 3-nums parts 11 | var parts = []; 12 | num = num.toString().split(''); 13 | while (num.length) { 14 | parts.push(num.splice(-3, 3)); 15 | } 16 | 17 | return parts.reduce(function (pre, item, index) { 18 | var words = say(item); 19 | var q = quantityHash[index]; 20 | 21 | if (words) { 22 | words = q ? [words, q] : [words]; 23 | pre = [].concat(words, pre); 24 | } 25 | 26 | return pre; 27 | }, []).join(' '); 28 | }; 29 | 30 | function say(num) { 31 | num = parseInt(num.join('')); 32 | if (num === 0) return ''; 33 | 34 | var numWords = ['' , 'One', 'Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight', 'Nine']; 35 | 36 | var hash = { 37 | '10': 'Ten', 38 | '11': 'Eleven', 39 | '12': 'Twelve', 40 | '13': 'Thirteen', 41 | '14': 'Fourteen', 42 | '15': 'Fifteen', 43 | '16': 'Sixteen', 44 | '17': 'Seventeen', 45 | '18': 'Eighteen', 46 | '19': 'Nineteen' 47 | }; 48 | 49 | var tenHash = [ '', '', 'Twenty', 'Thirty', 'Forty', 'Fifty', 'Sixty', 'Seventy', 'Eighty', 'Ninety']; 50 | 51 | var res = []; 52 | var item; 53 | 54 | num = ('000' + num).substr(-3, 3).split(''); 55 | 56 | // hundred 57 | item = num[0]; 58 | if (item !== '0') { 59 | res.push(numWords[item] + ' Hundred'); 60 | } 61 | 62 | // decade 63 | var skipOne = false; 64 | var val = ''; 65 | item = num[1]; 66 | if (item !== '0') { 67 | if (item === '1') { 68 | skipOne = true; 69 | val = hash[num.join('').substr(1)]; 70 | } else { 71 | val = tenHash[parseInt(item)]; 72 | } 73 | 74 | res.push(val); 75 | } 76 | 77 | // one 78 | item = num[2]; 79 | if (item !== '0' && !skipOne) { 80 | res.push(numWords[parseInt(item)]); 81 | } 82 | 83 | return res.join(' '); 84 | } 85 | 86 | var eq = require('assert').equal; 87 | 88 | eq(numberToWords(0), 'Zero'); 89 | eq(numberToWords(1), 'One'); 90 | eq(numberToWords(16), 'Sixteen'); 91 | eq(numberToWords(2147), 'Two Thousand One Hundred Forty Seven'); 92 | eq(numberToWords(12147), 'Twelve Thousand One Hundred Forty Seven'); 93 | eq(numberToWords(1234567), 'One Million Two Hundred Thirty Four Thousand Five Hundred Sixty Seven'); 94 | -------------------------------------------------------------------------------- /js/integerToRoman/integer-to-roman.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert') 2 | /** 3 | * @param {number} num 4 | * @returns {string} 5 | */ 6 | var intToRoman = function(num) { 7 | var steps = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1] 8 | , dict = { 9 | '1000': 'M', '900': 'CM', '500': 'D', '400': 'CD', 10 | '100': 'C', '90': 'XC', '50': 'L', '40': 'XL', 11 | '10': 'X', '9': 'IX', '5': 'V', '4': 'IV', 12 | '1': 'I' 13 | }; 14 | 15 | var res = ''; 16 | 17 | for (var i = 0; i < steps.length; i++) { 18 | var step = steps[i] 19 | , m = parseInt(num / step) 20 | , num = num % step; 21 | 22 | if (m > 0) { 23 | res += repeat(dict[step], m); 24 | } 25 | 26 | if (num === 0) break; 27 | } 28 | 29 | return res; 30 | }; 31 | 32 | function repeat(str, num) { 33 | var res = ''; 34 | while (num > 0) { 35 | res += str; 36 | num --; 37 | } 38 | 39 | return res; 40 | } 41 | 42 | 43 | assert.equal(intToRoman(2015), 'MMXV'); 44 | assert.equal(intToRoman(1066), 'MLXVI', 'fail 1066'); 45 | assert.equal(intToRoman(1904), 'MCMIV', 'fail 1904'); 46 | -------------------------------------------------------------------------------- /js/invertBinaryTree/invert_binary_tree.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {TreeNode} root 3 | * @return {TreeNode} 4 | */ 5 | // solution 1: recursion 6 | var invertTree = function(root) { 7 | 8 | if (!root) return root; 9 | var left = root.left; 10 | var right = root.right; 11 | 12 | if (!right && !left) return root; 13 | 14 | root.right = invertTree(left); 15 | root.left = invertTree(right); 16 | 17 | return root; 18 | }; 19 | 20 | invertTree = function(root) { 21 | 22 | if (!root) return root; 23 | var stack = [root]; 24 | 25 | var current; 26 | var left; 27 | var right; 28 | while(stack.length) { 29 | current = stack.pop(); 30 | 31 | if (!current) continue; 32 | 33 | left = current.left; 34 | right = current.right; 35 | 36 | current.left = right; 37 | current.right = left; 38 | 39 | if (left) stack.push(left); 40 | if (right) stack.push(right); 41 | } 42 | 43 | return root; 44 | }; 45 | 46 | var Tree = require('leetcode').Tree; 47 | 48 | var eq = require('assert').deepEqual; 49 | eq(invertTree(Tree.create([1, 2, 3])), 50 | Tree.create([1, 3, 2])); 51 | 52 | 53 | eq(invertTree(Tree.create([4, 2, 7, 1, 3, 6, 9])), 54 | Tree.create([4, 7, 2, 9, 6, 3, 1])); 55 | -------------------------------------------------------------------------------- /js/isomorphicStrings/isomorphic_strings.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} s 3 | * @param {string} t 4 | * @return {boolean} 5 | */ 6 | var isIsomorphic = function(s, t) { 7 | var s = s.split(''); 8 | var t = t.split(''); 9 | 10 | if (new Set(s).size !== new Set(t).size) return false; 11 | 12 | var zip = new Set(); 13 | s.forEach(function (item, i) { 14 | zip.add(s[i] + ' ' + t[i]) 15 | }); 16 | 17 | return new Set(zip).size === new Set(s).size; 18 | }; 19 | 20 | var eq = require('assert').equal; 21 | 22 | eq(isIsomorphic('egg', 'add'), true); 23 | eq(isIsomorphic('egg', 'ddd'), false); 24 | -------------------------------------------------------------------------------- /js/letterCombinationsOfAPhoneNumber/letter_combinations_of_a_phone_number.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} digits 3 | * @return {string[]} 4 | */ 5 | var letterCombinations = function(digits) { 6 | var map = [ '0', '1', ['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i'], ['j', 'k', 'l'], ['m', 'n', 'o'], ['p', 'q', 'r', 's'], ['t', 'u', 'v'], ['w', 'x', 'y', 'z']]; 7 | 8 | if (digits.length === 0) return []; 9 | var digitsArr = digits.split('').map((val) => parseInt(val, 10)).map((val) => map[val]); 10 | 11 | var res = []; 12 | for (var i = 0; i < digitsArr.length; i++) { 13 | res = merge(res, digitsArr[i]); 14 | } 15 | 16 | return res; 17 | }; 18 | 19 | function merge(srcArr, letters) { 20 | if (srcArr.length === 0) { 21 | return letters.slice(0); 22 | } 23 | 24 | var res = []; 25 | 26 | for (var i = 0; i < letters.length; i ++) { 27 | var val = letters[i]; 28 | 29 | srcArr.forEach(item => { 30 | res.push(item + val); 31 | }); 32 | } 33 | 34 | return res; 35 | } 36 | 37 | var eq = require('assert').deepEqual; 38 | 39 | eq(letterCombinations('23'), [ 'ad', 'bd', 'cd', 'ae', 'be', 'ce', 'af', 'bf', 'cf']); 40 | eq(letterCombinations(''), []); 41 | 42 | -------------------------------------------------------------------------------- /js/linkedListCycleIi/linked_list_cycle_ii.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * function ListNode(val) { 4 | * this.val = val; 5 | * this.next = null; 6 | * } 7 | */ 8 | 9 | /** 10 | * @param {ListNode} head 11 | * @return {ListNode} 12 | */ 13 | var detectCycle = function(head) { 14 | var slow = head; 15 | var fast = head; 16 | 17 | while(slow && fast) { 18 | slow = slow.next; 19 | fast = fast.next; 20 | 21 | if (!fast) return null; 22 | fast = fast.next; 23 | 24 | if (fast === slow) break; 25 | } 26 | if (!slow || !fast) return null; 27 | 28 | // when head is the loop start 29 | if (slow === head) return head; 30 | 31 | var finder = head; 32 | while(true) { 33 | slow = slow.next; 34 | finder = finder.next; 35 | 36 | if (slow === finder) { 37 | break; 38 | } 39 | } 40 | 41 | return finder; 42 | }; 43 | -------------------------------------------------------------------------------- /js/longestPalindromicSubstring/longest_palindromic_substring.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} s 3 | * @return {string} 4 | */ 5 | var longestPalindrome = function(s) { 6 | // 1 3 4 5 6 5 6 5 6 5 7 7 | 8 | var length = s.length; 9 | if (length <= 1) return s; 10 | 11 | var len = 1; 12 | var ans; 13 | 14 | for (var i = 0; i < length - 1; i ++) { 15 | // abba pattern 16 | var even = getSub(s, i, i + 1); 17 | // aba pattern 18 | var odd = getSub(s, i - 1, i + 1) 19 | odd[0] += 1; 20 | 21 | var tmp = even[0] > odd[0] ? even : odd; 22 | if (tmp[0] > len) { 23 | len = tmp[0]; 24 | ans = s.substr(tmp[1], len); 25 | } 26 | } 27 | 28 | return ans; 29 | }; 30 | 31 | // find longest palindrome 32 | // left and right is the start point to search two direction 33 | function getSub(s, left, right) { 34 | var length = s.length; 35 | var len = 0; 36 | while (left >= 0 && right <= length - 1) { 37 | if (s.charAt(left) === s.charAt(right)) { 38 | len += 2; 39 | left -= 1; 40 | right += 1; 41 | } else { 42 | break; 43 | } 44 | } 45 | 46 | return [len, left + 1]; 47 | } 48 | 49 | 50 | var eq = require('assert').equal; 51 | 52 | eq(longestPalindrome('123456654345665'), '56654345665'); 53 | eq(longestPalindrome('1232112'), '12321'); 54 | eq(longestPalindrome('11'), '11'); 55 | -------------------------------------------------------------------------------- /js/majorityElement/majority_element.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @return {number} 4 | */ 5 | // a genius solution, check http://is.gd/j5nJsb 6 | var majorityElement = function(nums) { 7 | var major; 8 | var count = 0; 9 | var mid = (nums.length >> 1); 10 | 11 | for (var i = 0; i< nums.length; i ++) { 12 | var val = nums[i]; 13 | if (count === 0) { 14 | count = 1; 15 | major = val; 16 | } else if (major === val) { 17 | count ++; 18 | } else { 19 | count --; 20 | } 21 | 22 | if (count > mid) break; 23 | } 24 | 25 | return major; 26 | }; 27 | 28 | 29 | var eq = require('assert').equal; 30 | eq(majorityElement([1, 2, 3, 4, 5, 5, 5, 5, 5]), 5); 31 | eq(majorityElement([1, 2, 5, 5, 5, 5]), 5); 32 | eq(majorityElement([5, 5, 3]), 5); 33 | -------------------------------------------------------------------------------- /js/meetingRooms/meeting_rooms.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for an interval. 3 | * function Interval(start, end) { 4 | * this.start = start; 5 | * this.end = end; 6 | * } 7 | */ 8 | /** 9 | * @param {Interval[]} intervals 10 | * @return {boolean} 11 | */ 12 | var canAttendMeetings = function(intervals) { 13 | var intervals = intervals.sort(function (a, b) { 14 | return a.start - b.start; 15 | }); 16 | 17 | for (var i = 0; i < intervals.length - 1; i ++) { 18 | if (intervals[i].end > intervals[i + 1].start) return false; 19 | } 20 | 21 | return true; 22 | }; 23 | -------------------------------------------------------------------------------- /js/mergeSortedArray/merge_sorted_array.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums1 3 | * @param {number} m 4 | * @param {number[]} nums2 5 | * @param {number} n 6 | * @return {void} Do not return anything, modify nums1 in-place instead. 7 | */ 8 | // var merge = function(nums1, m, nums2, n) { 9 | // // only keep m items 10 | // nums1.splice(m, nums1.length - m); 11 | // 12 | // var low = 0; 13 | // var high; 14 | // var mid; 15 | // for (var i = 0; i < n; i++) { 16 | // high = m - 1; 17 | // while (low <= high) { 18 | // mid = low + ((high - low) >> 1); 19 | // 20 | // if (nums2[i] === nums1[mid]) { 21 | // low = mid; 22 | // } 23 | // if(nums2[i] < nums1[mid]) { 24 | // high = mid - 1; 25 | // } else { 26 | // low = mid + 1; 27 | // } 28 | // } 29 | // 30 | // nums1.splice(low, 0, nums2[i]); 31 | // low += 1; 32 | // m++; 33 | // } 34 | // }; 35 | 36 | //a much clever solution!!! 37 | var merge = function(nums1, m, nums2, n) { 38 | var i = m - 1; 39 | var j = n - 1; 40 | var k = m + n - 1; 41 | 42 | while (i >= 0 && j >= 0) { 43 | if (nums1[i] > nums2[j]) { 44 | nums1[k--] = nums1[i--]; 45 | } else { 46 | nums1[k--] = nums2[j--]; 47 | } 48 | } 49 | 50 | while(j >= 0) { 51 | nums1[k--] = nums2[j--]; 52 | } 53 | } 54 | 55 | 56 | var eq = require('assert').deepEqual; 57 | 58 | var num = [1,3,5]; 59 | merge(num, num.length, [2,4], 2); 60 | eq(num, [1,2,3,4,5]); 61 | 62 | num = [0]; 63 | merge(num, 0, [5], 1); 64 | eq(num, [5]); 65 | 66 | num = [4]; 67 | merge(num, num.length, [5], 1); 68 | eq(num, [4,5]); 69 | 70 | num = [4]; 71 | merge(num, num.length, [3], 1); 72 | eq(num, [3,4]); 73 | 74 | num = [4, 5]; 75 | merge(num, num.length, [4, 5], 2); 76 | eq(num, [4,4, 5, 5]); 77 | -------------------------------------------------------------------------------- /js/missingNumber/missing_number.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @return {number} 4 | */ 5 | // this solution may overflow 6 | //var missingNumber = function(nums) { 7 | // var len = nums.length; 8 | // var expect = (len * (len + 1))/2; 9 | // 10 | // var sum = 0; 11 | // for (var i = 0; i < len; i++) { 12 | // sum += nums[i]; 13 | // } 14 | // 15 | // return expect - sum; 16 | //}; 17 | 18 | var missingNumber = function(nums) { 19 | var sum = 0; 20 | 21 | sum = nums.reduce(function (previous, current, index) { 22 | return previous ^ current ^ index; 23 | }, sum); 24 | 25 | sum ^= nums.length; 26 | 27 | return sum; 28 | }; 29 | 30 | 31 | var assert = require('assert'); 32 | 33 | assert.equal(missingNumber([1,2,3]), 0); 34 | assert.equal(missingNumber([0,2,3]), 1); 35 | assert.equal(missingNumber([0,1,2,4]), 3); 36 | -------------------------------------------------------------------------------- /js/moveZeroes/move_zeroes.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @return {void} Do not return anything, modify nums in-place instead. 4 | */ 5 | var moveZeroes = function(nums) { 6 | // 1 2 0 3 4 5 0 0 0 6 7 7 | var slow = nums.indexOf(0); 8 | 9 | if (!~slow) return; 10 | 11 | for (var i = 0; i < nums.length; i++) { 12 | if (nums[i] !== 0 && i > slow) { 13 | nums[slow ++] = nums[i]; 14 | } 15 | } 16 | 17 | if (slow !== -1) { 18 | while (slow < nums.length) { 19 | nums[slow++] = 0; 20 | } 21 | } 22 | }; 23 | 24 | 25 | var eq = require('assert').deepEqual; 26 | 27 | var arr = [1, 2, 3, 0, 0 , 0, 4, 1, 0]; 28 | moveZeroes(arr); 29 | eq(arr, [1,2,3,4,1, 0, 0, 0, 0]); 30 | 31 | arr = [1, 2, 3]; 32 | moveZeroes(arr); 33 | eq(arr, [1,2,3]); 34 | 35 | arr = [0, 1, 2, 3]; 36 | moveZeroes(arr); 37 | eq(arr, [1,2,3, 0]); 38 | 39 | arr = []; 40 | moveZeroes(arr); 41 | eq(arr, []); 42 | -------------------------------------------------------------------------------- /js/nextPermutation/README.md: -------------------------------------------------------------------------------- 1 | ## next permutation 2 | link: 3 | -------------------------------------------------------------------------------- /js/nextPermutation/next-permutation.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @return {void} Do not return anything, modify nums in-place instead. 4 | */ 5 | var nextPermutation = function(nums) { 6 | let swapped = 0; 7 | for (let index = nums.length - 1; index > 0; index --) { 8 | if (nums[index] > nums [index - 1]) { 9 | // find the closest number and swap, then revese array 10 | const closetIndex = findClosestNumberIndex(nums, index - 1); 11 | swapIndex(nums, index - 1, closetIndex); 12 | reverseArray(nums, index) 13 | swapped = 1; 14 | break; 15 | } 16 | } 17 | 18 | if (!swapped) reverseArray(nums, 0) 19 | }; 20 | 21 | // find the closest larger number index 22 | function findClosestNumberIndex(nums, index) { 23 | const value = nums[index]; 24 | let swapIndex = index + 1; 25 | for (let i = nums.length - 1; i > index; i --) { 26 | if (nums[i] > value) { 27 | swapIndex = i; 28 | break; 29 | } 30 | } 31 | 32 | return swapIndex; 33 | } 34 | 35 | function swapIndex(nums, i, j) { 36 | const value = nums[i]; 37 | nums[i] = nums[j]; 38 | nums[j] = value; 39 | } 40 | 41 | // in-place reverse array 42 | function reverseArray(nums, index) { 43 | const len = nums.length; 44 | for (let i = index, j = len - 1; i < j; ) { 45 | swapIndex(nums, i, j); 46 | i ++; 47 | j --; 48 | } 49 | } 50 | 51 | const deepEq = require('assert').deepStrictEqual; 52 | 53 | const inputs = [ 54 | [1, 4, 5, 2, 1], 55 | [1, 3, 2], 56 | [3, 2, 1], 57 | [1, 1, 5], 58 | [1] 59 | ]; 60 | 61 | const expects = [ 62 | [1, 5, 1, 2, 4], 63 | [2, 1, 3], 64 | [1, 2, 3], 65 | [1, 5, 1], 66 | [1] 67 | ]; 68 | 69 | inputs.forEach((input, index) => { 70 | nextPermutation(input); 71 | deepEq(input, expects[index]) 72 | }) 73 | -------------------------------------------------------------------------------- /js/numberComplement/README.md: -------------------------------------------------------------------------------- 1 | ## Number Complement 2 | link: 3 | Given a positive integer, output its complement number. The complement strategy is to flip the bits of its binary representation. 4 | 5 | Note: 6 | 7 | The given integer is guaranteed to fit within the range of a 32-bit signed integer. 8 | You could assume no leading zero bit in the integer’s binary representation. 9 | 10 | 11 | 12 | Example 1: 13 | 14 | Input: 5 15 | Output: 2 16 | Explanation: The binary representation of 5 is 101 (no leading zero bits), and its complement is 010. So you need to output 2. 17 | 18 | 19 | 20 | Example 2: 21 | 22 | Input: 1 23 | Output: 0 24 | Explanation: The binary representation of 1 is 1 (no leading zero bits), and its complement is 0. So you need to output 0. 25 | 26 | -------------------------------------------------------------------------------- /js/numberComplement/number-complement-2.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number} num 3 | * @return {number} 4 | */ 5 | var findComplement = function(num) { 6 | return Math.pow(2, num.toString(2).length) - num -1; 7 | }; 8 | 9 | 10 | var eq = require('assert').equal; 11 | eq(findComplement(5), 2); 12 | eq(findComplement(1), 0); 13 | -------------------------------------------------------------------------------- /js/numberComplement/number-complement.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number} num 3 | * @return {number} 4 | */ 5 | var findComplement = function(num) { 6 | var binaryStr = num.toString(2); 7 | 8 | var flag = false; 9 | var newStr = ''; 10 | binaryStr.split('').forEach(function (k) { 11 | var newK = k === '1' ? '0' : '1'; 12 | 13 | if (newK) flag = true; 14 | if (flag) newStr += newK; 15 | }); 16 | 17 | return parseInt(newStr, 2); 18 | }; 19 | 20 | 21 | var eq = require('assert').equal; 22 | eq(findComplement(5), 2); 23 | eq(findComplement(1), 0); 24 | -------------------------------------------------------------------------------- /js/numberOfDigitOne/number_of_digit_one.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number} n 3 | * @return {number} 4 | */ 5 | var countDigitOne = function(n) { 6 | }; 7 | -------------------------------------------------------------------------------- /js/paintFence/paint_fence.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number} n 3 | * @param {number} k 4 | * @return {number} 5 | */ 6 | var numWays = function(n, k) { 7 | 8 | }; 9 | -------------------------------------------------------------------------------- /js/palindromePermutation/palindrome_permutation.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} s 3 | * @return {boolean} 4 | */ 5 | var canPermutePalindrome = function(s) { 6 | var hash = {}; 7 | 8 | for(var i = 0; i< s.length; i ++) { 9 | val = s.charAt(i); 10 | hash[val] = hash[val] ? (hash[val] + 1) : 1; 11 | } 12 | 13 | return Object.keys(hash).reduce(function (pre, item) { 14 | return pre + (hash[item] % 2 === 0 ? 0 : 1); 15 | }, 0) <= 1; 16 | }; 17 | 18 | var eq = require('assert').equal; 19 | 20 | eq(canPermutePalindrome('bba'), true); 21 | eq(canPermutePalindrome('aa'), true); 22 | eq(canPermutePalindrome('a'), true); 23 | eq(canPermutePalindrome('ab'), false); 24 | -------------------------------------------------------------------------------- /js/pathSum/path_sum.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val) { 4 | * this.val = val; 5 | * this.left = this.right = null; 6 | * } 7 | */ 8 | /** 9 | * @param {TreeNode} root 10 | * @param {number} sum 11 | * @return {boolean} 12 | */ 13 | var hasPathSum = function(root, sum) { 14 | if (!root) return false; 15 | 16 | // leaf node 17 | if (!root.left && !root.right) { 18 | if (root.val !== sum) { 19 | return false 20 | } 21 | 22 | return true; 23 | } 24 | 25 | var val = root.val; 26 | var match = false; 27 | if (root.left) { 28 | match = hasPathSum(root.left, sum - val) 29 | } 30 | 31 | if (root.right) { 32 | match = match || hasPathSum(root.right, sum - val); 33 | } 34 | 35 | return match; 36 | }; 37 | -------------------------------------------------------------------------------- /js/perfectSquares/perfect_squares.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number} n 3 | * @return {number} 4 | */ 5 | var numSquares = function(n) { 6 | }; 7 | -------------------------------------------------------------------------------- /js/permutations/permutations.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @return {number[][]} 4 | */ 5 | var permute = function(nums) { 6 | var res = []; 7 | 8 | if(nums.length === 1) { 9 | return [nums]; 10 | } 11 | 12 | nums.forEach(function (val, index) { 13 | var newNums = nums.slice(0); 14 | newNums.splice(index, 1); 15 | 16 | var sorts = permute(newNums).map(function (item) { 17 | return [val].concat(item); 18 | }); 19 | 20 | res = res.concat(sorts); 21 | }) 22 | 23 | return res; 24 | }; 25 | 26 | 27 | var eq = require('assert').deepEqual; 28 | 29 | eq(permute([1]), [[1]]); 30 | eq(permute([1, 2]), [[1, 2], [2, 1]]); 31 | eq(permute([1, 2, 3]), [ 32 | [1, 2, 3], [1, 3, 2], 33 | [2, 1, 3], [2, 3, 1], 34 | [3, 1, 2], [3, 2, 1] 35 | ]); 36 | -------------------------------------------------------------------------------- /js/permutationsII/README.md: -------------------------------------------------------------------------------- 1 | # 47 Permutations II 2 | [link](https://leetcode.com/problems/permutations-ii/) 3 | 4 | Given a collection of numbers that might contain duplicates, return all possible unique permutations. 5 | 6 | For example, 7 | `[1,1,2]` have the following unique permutations: 8 | 9 | ``` 10 | [ 11 | [1,1,2], 12 | [1,2,1], 13 | [2,1,1] 14 | ] 15 | 16 | ``` 17 | -------------------------------------------------------------------------------- /js/permutationsII/permutations-ii.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @return {number[][]} 4 | */ 5 | var permuteUnique = function(nums) { 6 | if (nums.length === 1) return [nums]; 7 | 8 | var result = []; 9 | getPermute(nums, 0, result); 10 | return result; 11 | }; 12 | 13 | // position before `start` is already done 14 | function getPermute(arr, start, result) { 15 | if (start >= arr.length - 1) { 16 | // WARN: be aware of here, use shallow copy 17 | result.push(arr.slice(0)); 18 | return; 19 | }; 20 | 21 | var res = []; 22 | var hash = {}; 23 | for (var i = start; i < arr.length; i ++) { 24 | var val = arr[i]; 25 | if (hash[val]) continue; 26 | hash[val] = 1; 27 | 28 | swap(arr, i, start); 29 | getPermute(arr, start + 1, result); 30 | swap(arr, i, start); 31 | } 32 | } 33 | 34 | function swap(arr, i, j) { 35 | var vi = arr[i]; 36 | 37 | arr.splice(i, 1, arr[j]); 38 | arr.splice(j, 1, vi); 39 | } 40 | 41 | var eq = require('assert').deepEqual; 42 | 43 | eq(permuteUnique([1, 2, 1]), [ 44 | [1, 2, 1], 45 | [1, 1, 2], 46 | [2, 1, 1] 47 | ]); 48 | -------------------------------------------------------------------------------- /js/plusOne/plus_one.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} digits 3 | * @return {number[]} 4 | */ 5 | var plusOne = function(digits) { 6 | var carry = 1; 7 | 8 | for (var i = digits.length - 1; i >= 0; i--) { 9 | var val = digits[i]; 10 | digits[i] = (val + carry) % 10; 11 | carry = Math.floor((val + carry) / 10); 12 | 13 | if (!carry) break; 14 | } 15 | 16 | if (carry) digits.unshift(carry); 17 | return digits; 18 | }; 19 | 20 | 21 | var eq = require('assert').deepEqual; 22 | 23 | eq(plusOne([0]), [1]); 24 | eq(plusOne([1, 0, 9]), [1, 1, 0]); 25 | eq(plusOne([9]), [1, 0]); 26 | -------------------------------------------------------------------------------- /js/powerOfTwo/power_of_two.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number} n 3 | * @return {boolean} 4 | */ 5 | // var isPowerOfTwo = function(n) { 6 | // if (n === 1) return true; 7 | // var str = n.toString(2); 8 | // 9 | // return str.charAt(0) === '1' && parseInt(str.substr(1)) === 0; 10 | // }; 11 | 12 | 13 | // method 2 14 | // bit manipulation 15 | var isPowerOfTwo = function(n) { 16 | return (n > 0) && (n & (n-1)) === 0; 17 | }; 18 | var eq = require('assert').equal; 19 | 20 | eq(isPowerOfTwo(2), true); 21 | eq(isPowerOfTwo(1), true); 22 | eq(isPowerOfTwo(3), false); 23 | eq(isPowerOfTwo(4), true); 24 | -------------------------------------------------------------------------------- /js/powxN/powx_n.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number} x 3 | * @param {number} n 4 | * @return {number} 5 | */ 6 | var myPow = function(x, n) { 7 | if (n === 0) return 1; 8 | 9 | if (n < 0) { 10 | n = -n; 11 | x = 1/x; 12 | } 13 | 14 | var tmp = myPow(x, Math.floor(n/2)); 15 | tmp = tmp * tmp; 16 | 17 | if (n % 2 === 0) { 18 | return tmp; 19 | } else { 20 | return tmp * x; 21 | } 22 | } 23 | 24 | 25 | var eq = require('assert').equal; 26 | 27 | eq(myPow(2, 3), 8); 28 | eq(myPow(2, -3), 0.125); 29 | eq(myPow(2, 0), 1); 30 | -------------------------------------------------------------------------------- /js/productOfArrayExceptSelf/product_of_array_except_self.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @return {number[]} 4 | */ 5 | var productExceptSelf = function(nums) { 6 | var out = [1]; 7 | 8 | for (var i = 1; i < nums.length; i ++) { 9 | out[i] = out[i - 1] * nums[i - 1]; 10 | } 11 | 12 | var right = 1; 13 | for (var k = nums.length - 1; k >= 0; k--) { 14 | out[k] *= right; 15 | right *= nums[k]; 16 | } 17 | 18 | return out; 19 | }; 20 | 21 | var eq = require('assert').deepEqual; 22 | 23 | eq(productExceptSelf([1, 2, 3, 4]), [24,12,8,6]); 24 | eq(productExceptSelf([0, 2, 3, 4]), [24,0,0,0]); 25 | -------------------------------------------------------------------------------- /js/removeDuplicatesFromSortedArray/remove-duplicates-from-sorted-array.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} A 3 | * @return {number} 4 | */ 5 | var removeDuplicates = function(A) { 6 | 7 | if (A.length <= 1) return A.length; 8 | 9 | var pre; 10 | for (var i = 0; i < A.length;) { 11 | if (pre === A[i]) { 12 | A.splice(i, 1); 13 | } else { 14 | pre = A[i]; 15 | i ++; 16 | } 17 | } 18 | 19 | return A.length; 20 | }; 21 | 22 | var eq = require('assert').equal; 23 | 24 | var t = [1,2,3,4,4,5,5,5,6]; 25 | eq(removeDuplicates(t), 6); 26 | eq(removeDuplicates([]), 0); 27 | eq(removeDuplicates([1,1,1,1]), 1); 28 | -------------------------------------------------------------------------------- /js/removeDuplicatesFromSortedArrayIi/remove_duplicates_from_sorted_array_ii.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @return {number} 4 | */ 5 | var removeDuplicates = function(nums) { 6 | var pre = '#'; 7 | var count = 0; 8 | var appear = 0; 9 | for(var i = 0; i < nums.length; i++) { 10 | var val = nums[i]; 11 | if (val === pre) { 12 | if (appear < 2) { 13 | count ++; 14 | appear ++; 15 | } else { 16 | nums.splice(i, 1); 17 | i--; 18 | } 19 | } else { 20 | pre = val; 21 | appear = 1; 22 | count ++; 23 | } 24 | } 25 | 26 | return count; 27 | }; 28 | 29 | var eq = require('assert').equal; 30 | 31 | eq(removeDuplicates([]), 0) 32 | eq(removeDuplicates(['1', '1', '1']), 2) 33 | eq(removeDuplicates(['1', '1', '1', '2']), 3) 34 | eq(removeDuplicates([1,1,1,2,2,3]), 5) 35 | -------------------------------------------------------------------------------- /js/removeDuplicatesFromSortedList/remove_duplicates_from_sorted_list.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * function ListNode(val) { 4 | * this.val = val; 5 | * this.next = null; 6 | * } 7 | */ 8 | /** 9 | * @param {ListNode} head 10 | * @return {ListNode} 11 | */ 12 | var deleteDuplicates = function(head) { 13 | var current = head; 14 | var pre = null; 15 | 16 | while (current) { 17 | var val = current.val; 18 | 19 | if (pre && pre.val === val) { 20 | pre.next = current.next; 21 | } else { 22 | pre = current; 23 | } 24 | 25 | current = current.next; 26 | } 27 | 28 | return head; 29 | }; 30 | 31 | var eq = require('assert').deepEqual; 32 | var nodeList = require('leetcode').List; 33 | var l; 34 | 35 | l = nodeList.create([1, 2, 2, 3]); 36 | eq(nodeList.toArray(deleteDuplicates(l)), [1,2,3]); 37 | 38 | l = nodeList.create([1, 1, 1]); 39 | eq(nodeList.toArray(deleteDuplicates(l)), [1]); 40 | l = nodeList.create([]); 41 | eq(nodeList.toArray(deleteDuplicates(l)), []); 42 | -------------------------------------------------------------------------------- /js/removeElement/remove_element.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} A 3 | * @param {number} elem 4 | * @returns {number} 5 | */ 6 | var removeElement = function(A, elem) { 7 | var i; 8 | for (i = 0; i < A.length; ) { 9 | if (A[i] === elem) { 10 | A.splice(i, 1); 11 | } else { 12 | i ++; 13 | } 14 | } 15 | 16 | return A.length; 17 | }; 18 | -------------------------------------------------------------------------------- /js/removeLinkedListElements/remove_linked_list_elements.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * function ListNode(val) { 4 | * this.val = val; 5 | * this.next = null; 6 | * } 7 | */ 8 | /** 9 | * @param {ListNode} head 10 | * @param {number} val 11 | * @return {ListNode} 12 | */ 13 | var removeElements = function(head, val) { 14 | var dummy = {}; 15 | dummy.next = head; 16 | head = dummy; 17 | 18 | while(head && head.next) { 19 | if (head.next.val === val) { 20 | head.next = head.next.next; 21 | } else { 22 | head = head.next; 23 | } 24 | } 25 | 26 | return dummy.next; 27 | }; 28 | 29 | 30 | var eq = require('assert').deepEqual; 31 | var nodeList = require('leetcode').List; 32 | 33 | var list = nodeList.create([1, 2, 3, 4, 4]); 34 | list = removeElements(list, 4); 35 | eq(nodeList.toArray(list), [1,2,3]); 36 | 37 | list = nodeList.create([1, 1]); 38 | list = removeElements(list, 1); 39 | eq(nodeList.toArray(list), []); 40 | -------------------------------------------------------------------------------- /js/restoreIpAddresses/README.md: -------------------------------------------------------------------------------- 1 | ## Restore IP Addresses 2 | link: 3 | Given a string containing only digits, restore it by returning all possible valid IP address combinations. 4 | 5 | For example: 6 | 7 | > Given "25525511135", 8 | 9 | 10 | return 11 | 12 | > ["255.255.11.135", "255.255.111.35"]. (Order does not matter) 13 | -------------------------------------------------------------------------------- /js/restoreIpAddresses/restore-ip-addresses.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} s 3 | * @return {string[]} 4 | */ 5 | var restoreIpAddresses = function(s) { 6 | 7 | var result = []; 8 | getSolutions([], s, result); 9 | return result; 10 | }; 11 | 12 | function getSolutions(current, str, result) { 13 | if (current.length > 3) return; 14 | 15 | for (var l = 1; l <= 3 && l <= str.length; l ++) { 16 | var val = str.slice(0, l); 17 | 18 | // start with 0 but not '0' 19 | if (l > 1 && val.charAt(0) === '0') return; 20 | 21 | // not valid ip number 22 | if (parseInt(val, 10) > 255) return; 23 | 24 | var newCurrent = [].concat(current, [val]); 25 | 26 | // valid 27 | if (val === str && newCurrent.length === 4) { 28 | result.push(newCurrent.join('.')); 29 | return; 30 | } 31 | 32 | getSolutions(newCurrent, str.slice(l), result); 33 | } 34 | } 35 | 36 | var eq = require('assert').deepEqual; 37 | 38 | eq(restoreIpAddresses('25525511135'), [ '255.255.11.135', '255.255.111.35' ]); 39 | 40 | eq(restoreIpAddresses('0000'), ['0.0.0.0']); 41 | eq(restoreIpAddresses('0100'), ['0.1.0.0']); 42 | -------------------------------------------------------------------------------- /js/reverseLinkedList/reverse_linked_list.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * function ListNode(val) { 4 | * this.val = val; 5 | * this.next = null; 6 | * } 7 | */ 8 | /** 9 | * @param {ListNode} head 10 | * @return {ListNode} 11 | */ 12 | var reverseList = function(head) { 13 | var current = head; 14 | var pre = null; 15 | while(current) { 16 | var tmp = current.next; 17 | current.next = pre; 18 | pre = current; 19 | current = tmp; 20 | } 21 | 22 | head = pre; 23 | 24 | return head; 25 | }; 26 | -------------------------------------------------------------------------------- /js/reverseString/reverse_string.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} s 3 | * @return {string} 4 | */ 5 | 6 | var reverseString = function(s) { 7 | return s.split('').reverse().join(''); 8 | }; 9 | 10 | var eq = require('assert').equal; 11 | 12 | eq(reverseString('hello'), 'olleh'); 13 | eq(reverseString(''), ''); 14 | eq(reverseString('h'), 'h'); 15 | -------------------------------------------------------------------------------- /js/reverseVowelsOfAString/reverse_vowels_of_a_string.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @param {string} s 4 | * @return {string} 5 | * @example 6 | * Given s = "hello", return "holle". 7 | * Given s = "leetcode", return "leotcede". 8 | */ 9 | var reverseVowels = function(s) { 10 | var list = s.split(''); 11 | var vowels = ['a', 'e', 'i', 'o', 'u']; 12 | var isVowel = function(c) { return vowels.indexOf(c.toLowerCase()) !== -1; } 13 | 14 | var start = 0; 15 | var end = list.length - 1; 16 | var isStartValid = false; 17 | var isEndValid = false; 18 | 19 | while(start < end) { 20 | if (!isVowel(list[start])) { 21 | start ++; 22 | } else { 23 | isStartValid = true; 24 | } 25 | 26 | if (!isVowel(list[end])) { 27 | end --; 28 | } else { 29 | isEndValid = true; 30 | } 31 | 32 | // swap element and reset flags 33 | if (isStartValid && isEndValid) { 34 | var tmp = list[start]; 35 | list[start] = list[end]; 36 | list[end] = tmp; 37 | 38 | start ++; 39 | isStartValid = false; 40 | end --; 41 | isEndValid = false; 42 | } 43 | } 44 | 45 | return list.join(''); 46 | }; 47 | 48 | 49 | var eq = require('assert').equal; 50 | 51 | eq(reverseVowels('leetcode'), 'leotcede') 52 | eq(reverseVowels('lttt'), 'lttt') 53 | eq(reverseVowels('eoot'), 'ooet') 54 | eq(reverseVowels('Aot'), 'oAt') 55 | 56 | -------------------------------------------------------------------------------- /js/reverseWordsInAString/reverse_words_in_a_string.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} str 3 | * @returns {string} 4 | */ 5 | // O(n) space 6 | var reverseWords = function(str) { 7 | var words = str.trim().split(/\s+/); 8 | 9 | return words.reverse().join(' ') 10 | }; 11 | 12 | var eq = require('assert').equal; 13 | 14 | eq(reverseWords(' the sky is blue'), 'blue is sky the'); 15 | eq(reverseWords('the sky is blue'), 'blue is sky the'); 16 | eq(reverseWords('the sky is blue!'), 'blue! is sky the'); 17 | eq(reverseWords('the sky is blue !'), '! blue is sky the'); 18 | -------------------------------------------------------------------------------- /js/reverseWordsInAStringIi/reverse_words_in_a_string_ii-2.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {character[]} str 3 | * @return {void} Do not return anything, modify the string in-place instead. 4 | */ 5 | var reverseWords = function(words) { 6 | // here you are! ==> are! you here 7 | // ['h', 'e', 'r', 'e', ' ', 'y', 'o', 'u', ' ', 'a', 'r', 'e', '!'] 8 | words.unshift(' '); 9 | var len = words.length; 10 | var current = 0; 11 | var count = 0; 12 | var word; 13 | 14 | for (var i = len - 1; i >= 0; i--) { 15 | var val = words[len - 1 - count]; 16 | 17 | if (val === ' ') { 18 | if (count !== 0) { 19 | word = words.splice(-count, count); 20 | [].splice.apply(words, [current, 0].concat(word)); 21 | } 22 | // current move forward 23 | current = current + count; 24 | words.splice(-1, 1); 25 | words.splice(current, 0, ' '); 26 | count = 0; 27 | current ++; 28 | } else { 29 | count ++; 30 | } 31 | } 32 | 33 | words.splice(-1, 1); 34 | }; 35 | 36 | var eq = require('assert').deepEqual; 37 | var words; 38 | 39 | words = 'here you are haah'.split(''); 40 | reverseWords(words); 41 | eq(words, 'haah are you here'.split('')); 42 | 43 | words = 'here you are haah!'.split(''); 44 | reverseWords(words); 45 | eq(words, 'haah! are you here'.split('')); 46 | 47 | words = 'here ! %%%'.split(''); 48 | reverseWords(words); 49 | eq(words, '%%% ! here'.split('')); 50 | 51 | -------------------------------------------------------------------------------- /js/reverseWordsInAStringIi/reverse_words_in_a_string_ii.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {character[]} str 3 | * @return {void} Do not return anything, modify the string in-place instead. 4 | */ 5 | 6 | /** 7 | * a much simple version 8 | **/ 9 | var reverseWords = function(words) { 10 | words = words.reverse(); 11 | 12 | var start = 0; 13 | var val; 14 | for (var i = 0; i < words.length; i ++) { 15 | val = words[i]; 16 | if (val === ' ') { 17 | reverseWord(words, start, i - 1); 18 | start = i + 1; 19 | } 20 | } 21 | reverseWord(words, start, i - 1); 22 | } 23 | 24 | function reverseWord(arr, start, end) { 25 | if (start >= end || end >= arr.length) return; 26 | 27 | while (start < end) { 28 | tmp = arr[start]; 29 | arr[start] = arr[end]; 30 | arr[end] = tmp; 31 | start ++; 32 | end --; 33 | } 34 | } 35 | 36 | var eq = require('assert').deepEqual; 37 | var words; 38 | 39 | words = 'here you are haah'.split(''); 40 | reverseWords(words); 41 | eq(words, 'haah are you here'.split('')); 42 | 43 | words = 'here you are haah!'.split(''); 44 | reverseWords(words); 45 | eq(words, 'haah! are you here'.split('')); 46 | 47 | words = 'here ! %%%'.split(''); 48 | reverseWords(words); 49 | eq(words, '%%% ! here'.split('')); 50 | 51 | -------------------------------------------------------------------------------- /js/romanToInteger/roman-to-integer.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | 3 | /** 4 | * @param {string} str 5 | * @returns {number} 6 | */ 7 | var romanToInt = function(str) { 8 | var dict = { 9 | 'M': 1000 10 | , 'CM': 900 11 | , 'D': 500 12 | , 'CD': 400 13 | , 'C': 100 14 | , 'XC': 90 15 | , 'L': 50 16 | , 'XL': 40 17 | , 'X': 10 18 | , 'IX': 9 19 | , 'V': 5 20 | , 'IV': 4 21 | , 'I': 1 22 | }; 23 | 24 | var sum = 0; 25 | for (var i = 0; i < str.length;) { 26 | var part = ''; 27 | if ( i + 1 < str.length) { 28 | part = str.substr(i, 2); 29 | if (dict[part]) { 30 | sum += dict[part]; 31 | i += 2; 32 | continue; 33 | } 34 | } 35 | 36 | sum += dict[str[i]]; 37 | i++; 38 | } 39 | 40 | return sum; 41 | }; 42 | 43 | 44 | assert.equal(romanToInt('MMXV'), 2015, 'pass'); 45 | assert.equal(romanToInt('MLXVI'), 1066, 'pass'); 46 | assert.equal(romanToInt('MCMIV'), 1904, 'pass'); 47 | -------------------------------------------------------------------------------- /js/rotateArray/rotate_array.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @param {number} k 4 | * @return {void} Do not return anything, modify nums in-place instead. 5 | */ 6 | var rotate = function(nums, k) { 7 | k = k % nums.length; 8 | [].splice.apply(nums, [0, 0].concat(nums.splice(-k, k))); 9 | }; 10 | 11 | var eq = require('assert').deepEqual; 12 | 13 | var num = [1,2]; 14 | rotate(num, 1); 15 | eq(num, [2, 1]); 16 | 17 | num = [1,2]; 18 | rotate(num, 3); 19 | eq(num, [2, 1]); 20 | 21 | num = [1,2,3,4,5,6,7]; 22 | rotate(num, 3); 23 | eq(num, [5,6,7,1,2,3,4]); 24 | -------------------------------------------------------------------------------- /js/rotateList/rotate_list.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * function ListNode(val) { 4 | * this.val = val; 5 | * this.next = null; 6 | * } 7 | */ 8 | /** 9 | * @param {ListNode} head 10 | * @param {number} k 11 | * @return {ListNode} 12 | */ 13 | var rotateRight = function(head, k) { 14 | if (!head) return head; 15 | 16 | var tail = head; 17 | var len = 1; 18 | while (tail.next) { 19 | len ++; 20 | tail = tail.next; 21 | } 22 | 23 | // right rotate k = left rotate len - k 24 | k = k % len; 25 | if (k === 0) return head; 26 | 27 | // circle the link list 28 | tail.next = head; 29 | 30 | for (var i = 0; i < (len - k); i++) { 31 | tail = tail.next; 32 | } 33 | 34 | head = tail.next; 35 | tail.next = null; 36 | 37 | return head; 38 | }; 39 | -------------------------------------------------------------------------------- /js/sameTree/same_tree.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val) { 4 | * this.val = val; 5 | * this.left = this.right = null; 6 | * } 7 | */ 8 | /** 9 | * @param {TreeNode} p 10 | * @param {TreeNode} q 11 | * @return {boolean} 12 | */ 13 | var isSameTree = function(p, q) { 14 | if (!p) { 15 | if (p ^ q) return false; 16 | return true; 17 | } 18 | if (p.val !== q.val) return false; 19 | 20 | return isSameTree(p.left, q.left) && isSameTree(p.right, q.right); 21 | }; 22 | 23 | 24 | var tree = require('leetcode').Tree; 25 | var eq = require('assert').equal; 26 | 27 | var t1 = tree.create([1,null,2,3]) 28 | var t2 = tree.create([1,null,2,3]) 29 | 30 | eq(isSameTree(t1, t2), true); 31 | 32 | -------------------------------------------------------------------------------- /js/searchInRotatedSortedArray/search_in_rotated_sorted_array.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @param {number} target 4 | * @return {number} 5 | */ 6 | var search = function(nums, target) { 7 | var len = nums.length; 8 | var low = 0; 9 | var high = len - 1; 10 | 11 | while(low <= high) { 12 | mid = low + ((high - low) >> 1); 13 | var midVal = nums[mid]; 14 | 15 | if (midVal === target) return mid; 16 | 17 | if (target < midVal) { 18 | if ((midVal >= nums[low] && target >= nums[low]) || 19 | (target < nums[low] && midVal < nums[low])) { 20 | high = mid - 1; 21 | } else { 22 | low = mid + 1; 23 | } 24 | } else { 25 | if (midVal >= nums[low] || 26 | (midVal < nums[high] && target <= nums[high])) { 27 | low = mid + 1; 28 | } else { 29 | high = mid - 1; 30 | } 31 | } 32 | } 33 | 34 | return -1; 35 | }; 36 | 37 | // another version, logic is much simpler 38 | var search = function(nums, target) { 39 | var len = nums.length; 40 | var low = 0; 41 | var high = len - 1; 42 | 43 | while(low <= high) { 44 | mid = low + ((high - low) >> 1); 45 | var midVal = nums[mid]; 46 | 47 | if (midVal === target) return mid; 48 | 49 | if (nums[low] <= midVal) { 50 | if (target >= nums[low] && target < midVal) { 51 | high = mid - 1; 52 | } else { 53 | low = mid + 1; 54 | } 55 | } else { 56 | if (target <= nums[high] && target > midVal) { 57 | low = mid + 1; 58 | } else { 59 | high = mid - 1; 60 | } 61 | } 62 | } 63 | 64 | return -1; 65 | }; 66 | var eq = require('assert').equal; 67 | 68 | eq(search([4, 5, 6, 7, 0, 1, 2], 6), 2); 69 | eq(search([4, 5, 6, 7, 0, 1, 2], 1), 5); 70 | eq(search([4,5,6,7,8,1,2,3], 8), 4); 71 | eq(search([4], 6), -1); 72 | eq(search([4, 5], 5), 1); 73 | eq(search([5, 1, 3], 5), 0); 74 | eq(search([1, 3, 5], 1), 0); 75 | eq(search([5, 1, 2, 3, 4], 1), 1); 76 | -------------------------------------------------------------------------------- /js/searchInsertPosition/search_insert_position.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @param {number} target 4 | * @return {number} 5 | */ 6 | var searchInsert = function(nums, target) { 7 | // 1 3 5 6 5, 2 8 | // 1 3 5 6 2, 1 9 | // 4 2, 0 10 | var len = nums.length; 11 | var l = 0; 12 | var r = nums.length - 1; 13 | 14 | if (len === 0) return 0; 15 | 16 | var mid; 17 | while (l <= r) { 18 | mid = l + ((r - l) >> 1); 19 | 20 | // when equal, insert before the index, means use current index 21 | if (target === nums[mid]) return mid; 22 | 23 | if (target < nums[mid]) { 24 | r = mid - 1; 25 | } else { 26 | l = l + 1; 27 | } 28 | } 29 | 30 | return l; 31 | }; 32 | 33 | 34 | var eq = require('assert').equal; 35 | 36 | eq(searchInsert([1, 2, 4, 5, 6], 3), 2); 37 | eq(searchInsert([1, 2, 4, 5, 6], 4), 2); 38 | eq(searchInsert([1, 2, 5, 6], 7), 4); 39 | eq(searchInsert([1], 3), 1); 40 | eq(searchInsert([4], 3), 0); 41 | -------------------------------------------------------------------------------- /js/shortestWordDistance/shortest_word_distance.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string[]} words 3 | * @param {string} word1 4 | * @param {string} word2 5 | * @return {number} 6 | */ 7 | var shortestDistance = function(words, a, b) { 8 | var idxA = -1; 9 | var idxB = -1; 10 | var min = Infinity; 11 | 12 | words.forEach(function (val, i) { 13 | if (val === a) { 14 | idxA = i; 15 | } 16 | 17 | if (val === b) { 18 | idxB = i; 19 | } 20 | 21 | if (~idxA && ~idxB) { 22 | min = Math.min(min, Math.abs(idxA - idxB)); 23 | } 24 | }); 25 | 26 | return min; 27 | }; 28 | 29 | var eq = require('assert').equal; 30 | 31 | eq(shortestDistance(['a', 'b'], 'a', 'b'), 1) 32 | eq(shortestDistance(["a","c","b","a"], 'a', 'b'), 1) 33 | -------------------------------------------------------------------------------- /js/singleNumber/single_number.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @return {number} 4 | */ 5 | var singleNumber = function(nums) { 6 | return nums.reduce(function (pre, curr) { 7 | return pre ^ curr; 8 | }, 0) 9 | }; 10 | 11 | 12 | var eq = require('assert').equal; 13 | eq(singleNumber([1,1,2]), 2); 14 | eq(singleNumber([1,1,2, 2, 4, 4, 5]), 5); 15 | -------------------------------------------------------------------------------- /js/sortColors/sort_colors.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @return {void} Do not return anything, modify nums in-place instead. 4 | */ 5 | var sortColors = function(nums) { 6 | var len = nums.length; 7 | var idx2 = len - 1; 8 | var idx0 = 0; 9 | for (var i = 0; i < len; i++) { 10 | while (nums[i] === 2 && i < idx2) { 11 | swap(nums, i, idx2 --); 12 | } 13 | while (nums[i] === 0 && i > idx0) { 14 | swap(nums, i, idx0 ++) 15 | } 16 | } 17 | }; 18 | 19 | function swap(arr, i, j) { 20 | var tmp = arr[i]; 21 | arr[i] = arr[j]; 22 | arr[j] = tmp; 23 | } 24 | 25 | var eq = require('assert').deepEqual; 26 | 27 | var num = [0,1,0,1,2]; 28 | sortColors(num); 29 | eq(num, [0,0,1,1,2]); 30 | -------------------------------------------------------------------------------- /js/sqrtx/sqrtx.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number} x 3 | * @return {number} 4 | */ 5 | var mySqrt = function(x) { 6 | var low = 0; 7 | var high = x; 8 | var pre; 9 | if (x === 0) return 0; 10 | 11 | while (low <= high) { 12 | var mid = low + ((high - low) >> 1); 13 | 14 | // in case of overflow, use below instead of mid * mid 15 | if (mid === x / mid) return mid; 16 | 17 | if (mid > x / mid) { 18 | high = mid - 1; 19 | } else { 20 | pre = mid; 21 | low = mid + 1; 22 | } 23 | } 24 | 25 | return pre; 26 | }; 27 | 28 | 29 | var eq = require('assert').equal; 30 | eq(mySqrt(1), 1); 31 | eq(mySqrt(5), 2); 32 | eq(mySqrt(4), 2); 33 | eq(mySqrt(11), 3); 34 | -------------------------------------------------------------------------------- /js/strobogrammaticNumber/strobogrammatic_number.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} num 3 | * @return {boolean} 4 | */ 5 | var isStrobogrammatic = function(num) { 6 | var ns = ('' + num).split(''); 7 | var len = ns.length; 8 | var specials = [1, 8, 0]; 9 | var mid; 10 | 11 | if (len % 2) { 12 | mid = parseInt(ns[len >> 1]); 13 | if (!~specials.indexOf(mid)) return false; 14 | } 15 | 16 | var l = 0; 17 | var r = len - 1; 18 | while (l < r) { 19 | var vl = parseInt(ns[l]); 20 | var vr = parseInt(ns[r]); 21 | if ((vl === vr && ~specials.indexOf(vl)) || (vl === 6 && vr === 9) || (vl === 9 && vr === 6)) { 22 | l ++; 23 | r --; 24 | } else { 25 | return false; 26 | } 27 | } 28 | 29 | return true; 30 | }; 31 | 32 | var eq = require('assert').equal; 33 | 34 | eq(isStrobogrammatic(818), true); 35 | eq(isStrobogrammatic(22), false); 36 | eq(isStrobogrammatic(111), true); 37 | eq(isStrobogrammatic(101), true); 38 | eq(isStrobogrammatic(69269), false); 39 | eq(isStrobogrammatic(69169), true); 40 | -------------------------------------------------------------------------------- /js/strobogrammaticNumberIi/strobogrammatic_number_ii.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number} n 3 | * @return {string[]} 4 | */ 5 | var findStrobogrammatic = function(n) { 6 | return sub(n, n); 7 | }; 8 | 9 | function sub(n, m) { 10 | if (n === 0) return ['']; 11 | if (n === 1) return ['0', '1', '8']; 12 | 13 | var tmp = sub(n - 2, m); 14 | var res = []; 15 | 16 | tmp.forEach(function (item) { 17 | if (n !== m) { 18 | res.push('0' + item + '0'); 19 | } 20 | 21 | res.push('1' + item + '1'); 22 | res.push('6' + item + '9'); 23 | res.push('8' + item + '8'); 24 | res.push('9' + item + '6'); 25 | 26 | }); 27 | 28 | return res; 29 | 30 | } 31 | 32 | 33 | var eq = require('assert').deepEqual; 34 | 35 | eq(findStrobogrammatic(2), ["11","69","88","96"]); 36 | eq(findStrobogrammatic(3), 37 | [ 38 | '101', 39 | '609', 40 | '808', 41 | '906', 42 | '111', 43 | '619', 44 | '818', 45 | '916', 46 | '181', 47 | '689', 48 | '888', 49 | '986' 50 | ] 51 | ); 52 | -------------------------------------------------------------------------------- /js/subsets/README.md: -------------------------------------------------------------------------------- 1 | ## Subsets 2 | link: 3 | 4 | Given a set of distinct integers, nums, return all possible subsets. 5 | 6 | Note: The solution set must not contain duplicate subsets. 7 | 8 | 9 | For example, 10 | If nums = [1,2,3], a solution is: 11 | 12 | 13 | 14 | [ 15 | [3], 16 | [1], 17 | [2], 18 | [1,2,3], 19 | [1,3], 20 | [2,3], 21 | [1,2], 22 | [] 23 | ] 24 | -------------------------------------------------------------------------------- /js/subsets/subsets-v1.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @return {number[][]} 4 | */ 5 | var subsets = function(nums) { 6 | return getSolutions(nums); 7 | }; 8 | 9 | function getSolutions(nums) { 10 | if (nums.length === 0) { 11 | return [[]]; 12 | } 13 | 14 | var resNext = getSolutions(nums.slice(1)); 15 | var current = nums[0]; 16 | 17 | // n and n - 1 18 | var res = [].concat(resNext); 19 | for (var i = 0; i < resNext.length; i++) { 20 | var val = resNext[i]; 21 | res.push([].concat(current, val)); 22 | } 23 | 24 | return res; 25 | } 26 | -------------------------------------------------------------------------------- /js/subsets/subsets.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @return {number[][]} 4 | */ 5 | var subsets = function(nums) { 6 | 7 | var mem = []; 8 | var len = nums.length; 9 | 10 | for (var i = 0; i < len; i++) { 11 | var min = nums[i]; 12 | var idx = i; 13 | for (var k = i + 1; k < len; k++) { 14 | if (nums[k] < min) { 15 | min = nums[k]; 16 | idx = k; 17 | } 18 | } 19 | 20 | var tmp = []; 21 | mem.forEach(function (item) { 22 | // use concat instead of push, to clone item, instead of changing 23 | var val = [].concat(item, min); 24 | tmp.push(val); 25 | }); 26 | 27 | // make i the latest smallest one 28 | swap(nums, i, idx); 29 | mem = mem.concat(tmp); 30 | mem.push([min]); 31 | } 32 | 33 | mem.push([]); 34 | return mem; 35 | }; 36 | 37 | function swap(arr, i, j) { 38 | var tmp = arr[i]; 39 | arr[i] = arr[j]; 40 | arr[j] = tmp; 41 | } 42 | 43 | 44 | var eq = require('assert').equal; 45 | 46 | eq(subsets([4, 2, 3]).length, 8) 47 | -------------------------------------------------------------------------------- /js/sumOfTwoIntegers/sum-of-two-integers.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number} a 3 | * @param {number} b 4 | * @return {number} 5 | */ 6 | var getSum = function(a, b) { 7 | 8 | var sum = a; 9 | 10 | // @see https://en.wikipedia.org/wiki/Adder_%28electronics%29#Half_adder 11 | while (b !== 0) { 12 | // calculate sum without the carry 13 | sum = a ^ b; 14 | // calculate carry 15 | b = (a & b) << 1; 16 | 17 | a = sum; 18 | } 19 | 20 | return sum; 21 | }; 22 | 23 | 24 | var eq = require('assert').equal; 25 | 26 | eq(getSum(0, 1) , 1); 27 | eq(getSum(1, 0) , 1); 28 | eq(getSum(11, 3) , 14); 29 | -------------------------------------------------------------------------------- /js/sumRootToLeafNumbers/sum_root_to_leaf_numbers.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {TreeNode} root 3 | * @return {number} 4 | **/ 5 | var sumNumbers = function(root) { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /js/swapNodesInPairs/swap-nodes-in-pairs.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * function ListNode(val) { 4 | * this.val = val; 5 | * this.next = null; 6 | * } 7 | */ 8 | 9 | function ListNode(val) { 10 | this.val = val; 11 | this.next = null; 12 | } 13 | 14 | /** 15 | * @param {ListNode} head 16 | * @returns {ListNode} 17 | */ 18 | var swapPairs = function(head) { 19 | 20 | if (!(head && head.next)) return head; 21 | var sentinel = new ListNode(); 22 | sentinel.next = head; 23 | 24 | var cursor = sentinel; 25 | while(cursor.next && cursor.next.next) { 26 | var n = cursor.next; 27 | var nn = n.next; 28 | 29 | // swap 30 | n.next = nn.next; 31 | nn.next = n; 32 | cursor.next = nn; 33 | 34 | cursor = n; 35 | } 36 | 37 | return sentinel.next; 38 | }; 39 | 40 | function a2l(arr) { 41 | var guard = new ListNode() 42 | , curr = guard; 43 | for (var i =0; i < arr.length; i++) { 44 | curr.next = new ListNode(arr[i]); 45 | curr = curr.next; 46 | } 47 | 48 | return guard.next; 49 | } 50 | 51 | function pl(head) { 52 | while (head) { 53 | head = head.next; 54 | } 55 | } 56 | 57 | 58 | pl(swapPairs(a2l(['1', '2', '3']))) 59 | pl(swapPairs(a2l(['1', '2', '3', '4']))) 60 | 61 | -------------------------------------------------------------------------------- /js/twoSum/two_sum.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @param {number} target 4 | * @return {number[]} 5 | */ 6 | var twoSum = function(nums, target) { 7 | var hash = {}; 8 | 9 | var val; 10 | for (var i = 0; i < nums.length; i ++) { 11 | val = nums[i]; 12 | if (hash[target - val]) { 13 | return [hash[target - val], i + 1]; 14 | } 15 | 16 | hash[val] = i + 1; 17 | } 18 | }; 19 | 20 | 21 | var eq = require('assert').deepEqual; 22 | 23 | eq(twoSum([2, 7, 11, 15], 9), [1, 2]) 24 | eq(twoSum([2, 11, 13, 15], 17), [1, 4]) 25 | -------------------------------------------------------------------------------- /js/twoSumIiInputArrayIsSorted/two_sum_ii_input_array_is_sorted.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} numbers 3 | * @param {number} target 4 | * @return {number[]} 5 | */ 6 | // // binary search solution O(n*n) 7 | // var twoSum = function(numbers, target) { 8 | // var low; 9 | // var high; 10 | // var mid; 11 | // 12 | // for (var i = 0; i < numbers.length; i ++) { 13 | // low = i + 1; 14 | // high = numbers.length - 1; 15 | // 16 | // while(low <= high) { 17 | // mid = low + ((high - low) >> 1); 18 | // var val = numbers[i] + numbers[mid]; 19 | // 20 | // if (val === target) return [i + 1, mid + 1]; 21 | // 22 | // if (val > target) { 23 | // high = mid - 1; 24 | // } else { 25 | // low = low + 1; 26 | // } 27 | // } 28 | // } 29 | // }; 30 | 31 | // two-pointer O(n) time , O(1) space 32 | // var twoSum = function(numbers, target) { 33 | // var len = numbers.length; 34 | // var low = 0; 35 | // var high = len - 1; 36 | // var val; 37 | // while (low < high) { 38 | // val = numbers[low] + numbers[high]; 39 | // if (val === target) { 40 | // break; 41 | // } 42 | // 43 | // if(val > target) { 44 | // high = high - 1; 45 | // } else { 46 | // low = low + 1; 47 | // } 48 | // 49 | // } 50 | // 51 | // return [low+ 1, high + 1] 52 | // } 53 | 54 | // use hash, O(n) 55 | var twoSum = function(numbers, target) { 56 | var dict = {}; 57 | 58 | var num; 59 | for (var i = 0; i < numbers.length; i++) { 60 | num = numbers[i]; 61 | if (dict[target - num] !== undefined) { 62 | return [dict[target - num] + 1, i + 1] 63 | } 64 | 65 | dict[num] = i; 66 | } 67 | } 68 | 69 | var eq = require('assert').deepEqual; 70 | 71 | eq(twoSum([2, 7], 9), [1, 2]) 72 | eq(twoSum([2, 7, 11, 15], 17), [1, 4]) 73 | eq(twoSum([2, 7, 11, 15], 9), [1, 2]) 74 | -------------------------------------------------------------------------------- /js/twoSumIiiDataStructureDesign/two_sum_iii_data_structure_design.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @constructor 3 | */ 4 | var TwoSum = function() { 5 | this.dict = {}; 6 | }; 7 | 8 | /** 9 | * @param {number} input 10 | * @returns {void} 11 | */ 12 | TwoSum.prototype.add = function(input) { 13 | // no need to bigger that 2 14 | this.dict[input] = this.dict[input] ? 2 : 1; 15 | }; 16 | 17 | /** 18 | * @param {number} val 19 | * @returns {boolean} 20 | */ 21 | TwoSum.prototype.find = function(val) { 22 | var dict = this.dict; 23 | var keys = Object.keys(dict); 24 | 25 | for (var i = 0; i < keys.length; i++) { 26 | var key = parseInt(keys[i]); 27 | var target = val - key; 28 | 29 | if (!dict[target]) continue; 30 | 31 | if ((target === key && dict[target] === 2) || 32 | target !== key) { 33 | return true; 34 | } 35 | } 36 | 37 | return false; 38 | }; 39 | 40 | var eq = require('assert').equal; 41 | var ts = new TwoSum(); 42 | 43 | ts.add(0); 44 | ts.find(0) 45 | eq(ts.find(0), false); 46 | 47 | ts = new TwoSum(); 48 | ts.add(0); 49 | ts.add(0); 50 | ts.find(0) 51 | eq(ts.find(0), true); 52 | 53 | ts = new TwoSum(); 54 | ts.add(1); 55 | ts.add(3); 56 | ts.add(5); 57 | eq(ts.find(1), false); 58 | eq(ts.find(4), true); 59 | eq(ts.find(7), false); 60 | -------------------------------------------------------------------------------- /js/uglyNumber/ugly_number.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number} num 3 | * @return {boolean} 4 | */ 5 | var isUgly = function(n) { 6 | if (n <= 0) return false; 7 | if (n === 1) return true; 8 | 9 | while (n > 5) { 10 | if (n % 5 === 0) { 11 | n /= 5; 12 | } else if (n % 3 === 0) { 13 | n /= 3; 14 | } else if (n % 2 === 0) { 15 | n /= 2; 16 | } else { 17 | return false; 18 | } 19 | } 20 | 21 | return true; 22 | }; 23 | 24 | 25 | var eq = require('assert').equal; 26 | 27 | eq(isUgly(1), true) 28 | eq(isUgly(2), true) 29 | eq(isUgly(6), true) 30 | eq(isUgly(7), false) 31 | eq(isUgly(14), false) 32 | 33 | -------------------------------------------------------------------------------- /js/uglyNumberIi/ugly_number_ii.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number} n 3 | * @return {number} 4 | */ 5 | var nthUglyNumber = function(n) { 6 | var idx2 = 0, 7 | idx3 = 0, 8 | idx5 = 0; 9 | 10 | var factor2 = 2, 11 | factor3 = 3, 12 | factor5 =5; 13 | 14 | var ugly = [1]; 15 | 16 | for (var i = 1; i < n; i++) { 17 | var min = Math.min.call(null, factor2, factor3, factor5); 18 | ugly.push(min); 19 | 20 | if (factor2 === min) { 21 | factor2 = 2 * ugly[++idx2]; 22 | } 23 | 24 | if (factor3 === min) { 25 | factor3 = 3 * ugly[++idx3]; 26 | } 27 | 28 | if (factor5 === min) { 29 | factor5 = 5 * ugly[++idx5]; 30 | } 31 | } 32 | 33 | return ugly[n-1]; 34 | }; 35 | 36 | 37 | var eq = require('assert').equal; 38 | 39 | eq(nthUglyNumber(3), 3); 40 | eq(nthUglyNumber(10), 12); 41 | 42 | -------------------------------------------------------------------------------- /js/uniqueWordAbbreviation/unique_word_abbreviation.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @constructor 3 | * @param {string[]} dictionary 4 | */ 5 | var ValidWordAbbr = function(dictionary) { 6 | this.dict = dictionary; 7 | var hash = {}; 8 | 9 | dictionary.forEach(function (d) { 10 | var len = d.length; 11 | var abbr = d; 12 | 13 | if (len > 2) { 14 | abbr = d.charAt(0) + (len - 2) + d.charAt(len - 1); 15 | } 16 | 17 | if (hash[abbr]) { 18 | if (!~hash[abbr].indexOf(d)) { 19 | hash[abbr].push(d); 20 | } 21 | } else { 22 | hash[abbr] = [d]; 23 | } 24 | }); 25 | 26 | this.hash = hash; 27 | }; 28 | 29 | /** 30 | * @param {string} word 31 | * @return {bool} 32 | */ 33 | ValidWordAbbr.prototype.isUnique = function(word) { 34 | var abbr = word; 35 | var len = word.length; 36 | if (len > 2) { 37 | abbr = word.charAt(0) + (len - 2) + word.charAt(len - 1); 38 | } 39 | var abbrs = this.hash[abbr]; 40 | 41 | return !abbrs || (abbrs.length === 1 && abbrs[0] === word); 42 | }; 43 | 44 | 45 | /** 46 | * Your ValidWordAbbr object will be instantiated and called as such: 47 | * var vwa = new ValidWordAbbr(dictionary); 48 | * vwa.isUnique("word"); 49 | * vwa.isUnique("anotherWord"); 50 | */ 51 | 52 | var eq = require('assert').equal; 53 | 54 | var v = new ValidWordAbbr([ "deer", "door", "cake", "card" ]); 55 | eq(v.isUnique('dear'), false); 56 | eq(v.isUnique('cart'), true); 57 | eq(v.isUnique('cake'), true); 58 | v = new ValidWordAbbr(['a', 'a']); 59 | eq(v.isUnique('a'), true); 60 | -------------------------------------------------------------------------------- /js/validAnagram/valid_anagram.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} s 3 | * @param {string} t 4 | * @return {boolean} 5 | */ 6 | var isAnagram = function(s, t) { 7 | if (s.length !== t.length) return false; 8 | 9 | var hashA = hashrify(s); 10 | var hashB = hashrify(t); 11 | 12 | if (Object.keys(hashA).length !== Object.keys(hashB).length) return false; 13 | 14 | return !Object.keys(hashA).some(function (key) { 15 | return hashA[key] !== hashB[key]; 16 | }) 17 | 18 | }; 19 | 20 | function hashrify(s) { 21 | var hash = {}; 22 | var i; 23 | for (i = 0; i< s.length; i++) { 24 | var val = s.charAt(i); 25 | 26 | if (hash[val]) { 27 | hash[val] ++; 28 | } else { 29 | hash[val] = 1; 30 | } 31 | } 32 | 33 | return hash; 34 | } 35 | 36 | var assertEq = require('assert').equal; 37 | 38 | assertEq(isAnagram('a', 'b'), false) 39 | assertEq(isAnagram('abbba', 'bbbab'), false) 40 | assertEq(isAnagram('aaaa', 'aaaa'), true) 41 | 42 | -------------------------------------------------------------------------------- /js/validPalindrome/valid_palindrome.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} s 3 | * @return {boolean} 4 | */ 5 | var isPalindrome = function(s) { 6 | s = s.replace(/[\W]*/g, '').toLowerCase(); 7 | if (s === s.split('').reverse().join('')) return true; 8 | 9 | return false; 10 | }; 11 | 12 | var eq = require('assert').equal; 13 | 14 | eq(isPalindrome('A man, a plan, a canal: Panama'), true); 15 | eq(isPalindrome('race a car'), false); 16 | eq(isPalindrome(''), true); 17 | -------------------------------------------------------------------------------- /js/validSudoku/README.md: -------------------------------------------------------------------------------- 1 | ## valid sudoku 2 | link: 3 | -------------------------------------------------------------------------------- /js/validSudoku/valid-sudoku.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {character[][]} board 3 | * @return {boolean} 4 | */ 5 | var isValidSudoku = function(board) { 6 | 7 | // check all rows and columns along diagonal line, board[0][0], board[1][1], .., board[8][8] 8 | for (let i = 0; i < 9; i ++) { 9 | const isRowValid = isRowOrColumnValid(board, i); 10 | if (!isRowValid) return false; 11 | const isColumnValid = isRowOrColumnValid(board, i, true); 12 | if (!isColumnValid) return false; 13 | } 14 | 15 | // check boxes 16 | for (let i = 0; i < 3; i ++) { 17 | const rowStart = i * 3; 18 | for (let j = 0; j < 3; j ++) { 19 | const columnStart = j * 3; 20 | const isValid = isBoxValid(board, rowStart, columnStart) 21 | if (!isValid) return false; 22 | } 23 | } 24 | 25 | return true; 26 | }; 27 | 28 | function isRowOrColumnValid(board, index, isColumn) { 29 | const valueSet = new Set(); 30 | for (let i = 0; i < board.length; i ++) { 31 | let value = isColumn ? board[i][index] : board[index][i]; 32 | if (valueSet.has(value)) return false; 33 | if (value !== '.') { 34 | valueSet.add(value); 35 | } 36 | } 37 | 38 | return true; 39 | } 40 | 41 | function isBoxValid(board, rowStart, columnStart) { 42 | const valueSet = new Set(); 43 | for (let i = rowStart; i < rowStart + 3; i ++) { 44 | for (let j = columnStart; j < columnStart + 3; j ++) { 45 | const value = board[i][j]; 46 | if (valueSet.has(value)) return false; 47 | if (value !== '.') { 48 | valueSet.add(value); 49 | } 50 | } 51 | } 52 | return true; 53 | } 54 | 55 | const eq = require('assert').strictEqual; 56 | eq(isValidSudoku( 57 | [["5","3",".",".","7",".",".",".","."] 58 | ,["6",".",".","1","9","5",".",".","."] 59 | ,[".","9","8",".",".",".",".","6","."] 60 | ,["8",".",".",".","6",".",".",".","3"] 61 | ,["4",".",".","8",".","3",".",".","1"] 62 | ,["7",".",".",".","2",".",".",".","6"] 63 | ,[".","6",".",".",".",".","2","8","."] 64 | ,[".",".",".","4","1","9",".",".","5"] 65 | ,[".",".",".",".","8",".",".","7","9"] 66 | ]), true); 67 | 68 | eq(isValidSudoku( 69 | [["8","3",".",".","7",".",".",".","."] 70 | ,["6",".",".","1","9","5",".",".","."] 71 | ,[".","9","8",".",".",".",".","6","."] 72 | ,["8",".",".",".","6",".",".",".","3"] 73 | ,["4",".",".","8",".","3",".",".","1"] 74 | ,["7",".",".",".","2",".",".",".","6"] 75 | ,[".","6",".",".",".",".","2","8","."] 76 | ,[".",".",".","4","1","9",".",".","5"] 77 | ,[".",".",".",".","8",".",".","7","9"] 78 | ]), false); 79 | 80 | eq(isValidSudoku( 81 | [[".",".","4",".",".",".","6","3","."] 82 | ,[".",".",".",".",".",".",".",".","."] 83 | ,["5",".",".",".",".",".",".","9","."] 84 | ,[".",".",".","5","6",".",".",".","."] 85 | ,["4",".","3",".",".",".",".",".","1"] 86 | ,[".",".",".","7",".",".",".",".","."] 87 | ,[".",".",".","5",".",".",".",".","."] 88 | ,[".",".",".",".",".",".",".",".","."] 89 | ,[".",".",".",".",".",".",".",".","."]] 90 | ), false); 91 | 92 | eq(isValidSudoku( 93 | [[".",".",".",".","5",".",".","1","."] 94 | ,[".","4",".","3",".",".",".",".","."] 95 | ,[".",".",".",".",".","3",".",".","1"] 96 | ,["8",".",".",".",".",".",".","2","."] 97 | ,[".",".","2",".","7",".",".",".","."] 98 | ,[".","1","5",".",".",".",".",".","."] 99 | ,[".",".",".",".",".","2",".",".","."] 100 | ,[".","2",".","9",".",".",".",".","."] 101 | ,[".",".","4",".",".",".",".",".","."]] 102 | ), false) 103 | -------------------------------------------------------------------------------- /js/wordBreak/word_break.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} s 3 | * @param {set} wordDict 4 | * @return {boolean} 5 | */ 6 | var wordBreak = function(s, wordDict) { 7 | s = '#' + s; 8 | var dp = [true]; 9 | 10 | for (var i = 1; i < s.length; i ++) { 11 | for (var k = 0; k < i; k ++) { 12 | if (dp[k] && wordDict.has(s.substr(k + 1, i-k))) { 13 | dp[i] = true; 14 | break; 15 | } 16 | } 17 | } 18 | 19 | return !!dp[s.length - 1] 20 | }; 21 | 22 | 23 | 24 | var eq = require('assert').equal; 25 | eq(wordBreak('leetcode', new Set(['leet', 'code'])), true); 26 | eq(wordBreak('leettcode', new Set(['leet', 'code'])), false); 27 | eq(wordBreak('leet', new Set(['leet'])), true); 28 | eq(wordBreak('a', new Set(['a'])), true); 29 | eq(wordBreak('a', new Set([])), false); 30 | -------------------------------------------------------------------------------- /js/wordPattern/word_pattern.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} pattern 3 | * @param {string} str 4 | * @return {boolean} 5 | */ 6 | var wordPattern = function(pattern, str) { 7 | var ph = pattern.split(''); 8 | var sh = str.split(' '); 9 | var hash = {}; 10 | 11 | if (ph.length !== sh.length) return false; 12 | if (new Set(ph).size !== new Set(sh).size) return false; 13 | 14 | var zip = new Set(); 15 | 16 | ph.forEach(function (item, i) { 17 | zip.add(ph[i] + ' ' + sh[i]); 18 | }); 19 | 20 | return zip.size === new Set(ph).size; 21 | }; 22 | 23 | 24 | var eq = require('assert').equal; 25 | 26 | eq(wordPattern('abba', 'a b b a'), true); 27 | eq(wordPattern('abba', 'a b b b'), false); 28 | eq(wordPattern('abba', 'b b b b'), false); 29 | -------------------------------------------------------------------------------- /js/wordSearch/word_search.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /** 3 | * @param {character[][]} board 4 | * @param {string} word 5 | * @return {boolean} 6 | */ 7 | var exist = function(board, word) { 8 | 9 | board = board.map(function (item) { 10 | return item[0].split(''); 11 | }); 12 | 13 | for (var i = 0; i < board.length; i++) { 14 | for (var j = 0; j < board[0].length; j++) { 15 | if (isMatch(board, j, i, word, 0)) return true; 16 | } 17 | } 18 | 19 | return false; 20 | }; 21 | 22 | function isMatch(b, i, j, word, idx) { 23 | var mX = b[0].length; 24 | var mY = b.length; 25 | if (idx === word.length) return true; 26 | 27 | if (i < 0 || i >= mX || j < 0 || j >= mY || b[j][i] !== word.charAt(idx)) return false; 28 | 29 | b[j][i] = '&'; 30 | 31 | if (isMatch(b, i + 1, j, word, idx + 1) || 32 | isMatch(b, i - 1, j, word, idx + 1) || 33 | isMatch(b, i, j + 1, word, idx + 1) || 34 | isMatch(b, i, j - 1, word, idx + 1)) { 35 | return true; 36 | } 37 | 38 | b[j][i] = word.charAt(idx); 39 | return false; 40 | } 41 | 42 | 43 | var eq = require('assert').equal; 44 | 45 | var b = [ 46 | ["ABCE"], 47 | ["SFCS"], 48 | ["ADEE"] 49 | ]; 50 | 51 | eq(exist(b, 'ABCCED'), true); 52 | eq(exist(b, 'SEE'), true); 53 | eq(exist(b, 'SEEA'), false); 54 | 55 | b = [ ['aa'] ]; 56 | eq(exist(b, 'aa'), true); 57 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "leetcode": "^1.2.0" 4 | }, 5 | "scripts": { 6 | "test": "make test", 7 | "load": "./bin/load bin/loadProblem.js" 8 | }, 9 | "devDependencies": { 10 | "camelcase": "^6.2.0", 11 | "chalk": "^1.1.3", 12 | "cheerio": "^0.20.0", 13 | "mkdirp": "^0.5.1", 14 | "request": "^2.73.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /python/3sum.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | # @return a list of lists of length 3, [[val1,val2,val3]] 3 | def threeSum(self, num): 4 | num.sort(); 5 | l = len(num) 6 | if l < 3: 7 | return [] 8 | 9 | res = [] 10 | for i in range(l-2): 11 | # avoid duplicate 12 | if (i != 0 and num[i] == num[i - 1]): 13 | continue 14 | 15 | left = i + 1 16 | right = l - 1 17 | target = -num[i] 18 | 19 | while left < right: 20 | s = num[left] + num[right] 21 | if target == s: 22 | res.append([-target, num[left], num[right]]) 23 | 24 | # avoid duplicate 25 | while left < right: 26 | left += 1 27 | if num[left] > num[left - 1]: break 28 | 29 | # avoid duplicate 30 | while left < right: 31 | right -= 1 32 | if num[right] < num[right + 1]: break 33 | 34 | elif s < target: 35 | # avoid duplicate 36 | while left < right: 37 | left += 1 38 | if num[left] > num[left - 1]: break 39 | else: 40 | # avoid duplicate 41 | while left < right: 42 | right -= 1 43 | if num[right] < num[right + 1]: break 44 | 45 | return res 46 | 47 | 48 | s = Solution() 49 | assert s.threeSum([-1, 0, 1, 2, -1, -4]) == [[-1, -1, 2], [-1, 0, 1]] 50 | assert s.threeSum([-1, 0, 0, 0, 1, 2]) == [[-1, 0, 1], [0, 0 ,0]] 51 | -------------------------------------------------------------------------------- /python/_util.py: -------------------------------------------------------------------------------- 1 | 2 | # test code 3 | class ListNode: 4 | def __init__(self, x): 5 | self.val = x 6 | self.next = None 7 | 8 | def a2ll(l): 9 | ll = ListNode(l[0]) 10 | 11 | cursor = ll 12 | for i in range(1, len(l)): 13 | cursor.next = ListNode(l[i]) 14 | cursor = cursor.next 15 | 16 | return ll 17 | def pl(ll): 18 | while ll: 19 | print ll.val, 20 | ll = ll.next 21 | print 22 | -------------------------------------------------------------------------------- /python/add_two_numbers.py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | # class ListNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.next = None 6 | 7 | class Solution: 8 | # @return a ListNode 9 | def addTwoNumbers(self, l1, l2): 10 | 11 | sum0 = (l1.val + l2.val) % 10 12 | carry = (l1.val + l2.val) / 10 13 | 14 | # root 15 | root = ListNode(sum0) 16 | l1 = l1.next 17 | l2 = l2.next 18 | cursor = root 19 | while l1 and l2: 20 | v1 = l1.val 21 | v2 = l2.val 22 | 23 | s = (v1 + v2 + carry) 24 | val = s % 10 25 | carry = s / 10 26 | 27 | cursor.next = ListNode(val) 28 | cursor = cursor.next 29 | l1 = l1.next 30 | l2 = l2.next 31 | 32 | l2 = l2 if l2 else l1 33 | while l2: 34 | s = l2.val + carry 35 | val = s % 10 36 | carry = s / 10 37 | 38 | cursor.next = ListNode(val) 39 | cursor = cursor.next 40 | 41 | l2 = l2.next 42 | if carry != 0: 43 | cursor.next = ListNode(carry) 44 | 45 | return root 46 | 47 | 48 | ## test code 49 | # class ListNode: 50 | # def __init__(self, x): 51 | # self.val = x 52 | # self.next = None 53 | # 54 | # def a2ll(l): 55 | # ll = ListNode(l[0]) 56 | # 57 | # cursor = ll 58 | # for i in range(1, len(l)): 59 | # cursor.next = ListNode(l[i]) 60 | # cursor = cursor.next 61 | # 62 | # return ll 63 | # 64 | # s = Solution() 65 | # ll = s.addTwoNumbers(a2ll([7,0,3,6,7,3,2,1,5]), a2ll([9,2,5,5,6,1,2,2,4])) 66 | # while ll: 67 | # print ll.val, 68 | # ll = ll.next 69 | -------------------------------------------------------------------------------- /python/climbing_stairs.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | # @param n, an integer 3 | # @return an integer 4 | def climbStairs(self, n): 5 | if (n == 1): 6 | return 1 7 | count = 0 8 | d = {} 9 | for i in range(n + 1): 10 | m = n - i 11 | if m == 0: 12 | count += 1 13 | elif m % 2 == 0: 14 | key = str(i) + '_' + str(m) 15 | if key in d: 16 | val = d[key] 17 | else: 18 | val = self.getAn_m(i, m/2) 19 | 20 | count += val 21 | 22 | return count 23 | 24 | # A_m/n+1 25 | def getAn_m(self, n, m): 26 | if m == 0 or n == 0: 27 | return 1 28 | if m > n: 29 | return self.getAn_m(m, n) 30 | anm = 1 31 | amm = 1 32 | n = m + n 33 | for i in range(m): 34 | anm *= n - i 35 | amm *= i + 1 36 | 37 | return anm/amm 38 | 39 | 40 | s = Solution() 41 | assert s.climbStairs(1) == 1 42 | assert s.climbStairs(2) == 2 43 | assert s.climbStairs(3) == 3 44 | assert s.climbStairs(4) == 5 45 | assert s.climbStairs(5) == 8 46 | assert s.climbStairs(6) == 13 47 | -------------------------------------------------------------------------------- /python/generate_parentheses.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | # @param an integer 3 | # @return a list of string 4 | def generateParenthesis(self, n): 5 | if (n <= 0): 6 | return [] 7 | 8 | arr = [] 9 | self.g(n, 0, 0, '', arr) 10 | return arr 11 | 12 | ## 13 | # generate 14 | # @param n the length of the pairs 15 | # @param `left` the length the the left parentheses `(` 16 | # @param `right` the length the the right parentheses `)` 17 | # @param `s` current string of parentheses 18 | # @param `arr` list of the pairs 19 | ## 20 | def g(self, n, left, right, s, arr): 21 | if left < right: 22 | return 23 | 24 | if (left == right and left == n): 25 | arr.append(s) 26 | return 27 | if (left == n): 28 | self.g(n,left, right + 1, s + ')', arr) 29 | return 30 | 31 | self.g(n, left + 1, right, s + '(', arr); 32 | self.g(n, left, right + 1, s + ')', arr); 33 | 34 | 35 | s = Solution() 36 | assert s.generateParenthesis(3) == ["((()))", "(()())", "(())()", "()(())", "()()()"] 37 | assert s.generateParenthesis(2) == ["(())", "()()"] 38 | assert s.generateParenthesis(4) != ["(())", "()()"] 39 | -------------------------------------------------------------------------------- /python/implement_strstr.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | # @param haystack, a string 3 | # @param needle, a string 4 | # @return an integer 5 | def strStr(self, haystack, needle): 6 | lenh = len(haystack) 7 | lenn = len(needle) 8 | 9 | if (lenh < lenn): 10 | return -1 11 | 12 | lenSub = lenh 13 | idx = 0 14 | while lenSub >= lenn: 15 | if haystack[idx: idx + lenn] == needle: 16 | return idx 17 | else: 18 | idx += 1 19 | lenSub -= 1 20 | 21 | return -1 22 | 23 | s = Solution() 24 | assert s.strStr('abcdedggg', 'ggg') == 6 25 | assert s.strStr('ab', 'ggg') == -1 26 | assert s.strStr('abc', 'ggg') == -1 27 | -------------------------------------------------------------------------------- /python/intersection_of_two_linked_lists.py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | # class ListNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.next = None 6 | 7 | class Solution: 8 | # @param two ListNodes 9 | # @return the intersected ListNode 10 | def getIntersectionNode(self, headA, headB): 11 | lA = self.getlen(headA) 12 | lB = self.getlen(headB) 13 | if lA > lB: 14 | tmp = headA 15 | headA = headB 16 | headB = tmp 17 | tmp = lA 18 | lA = lB 19 | lB = tmp 20 | 21 | pA = headA 22 | pB = headB 23 | intersection = None 24 | for i in range(lB - lA): 25 | pB = pB.next 26 | while pB: 27 | if pB.val != pA.val: 28 | intersection = None 29 | elif not intersection: 30 | intersection = pB 31 | pB = pB.next 32 | pA = pA.next 33 | 34 | return intersection 35 | 36 | def getlen(self, head): 37 | c = head 38 | l = 0 39 | while c: 40 | l += 1 41 | c = c.next 42 | return l 43 | 44 | from _util import * 45 | s = Solution() 46 | # list A < list B 47 | n = s.getIntersectionNode(a2ll([1,2,4,5,6]), a2ll([2,1,3,6,5,6])); 48 | assert n.val == 5 49 | # list A > list B 50 | n = s.getIntersectionNode(a2ll([1,2,4,5,6]), a2ll([4,7,6])); 51 | assert n.val == 6 52 | # list A = list B 53 | n = s.getIntersectionNode(a2ll([4,5,6]), a2ll([4,7,6])); 54 | assert n.val == 6 55 | -------------------------------------------------------------------------------- /python/longest_common_prefix.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | # @return a string 3 | def longestCommonPrefix(self, strs): 4 | lenstrs = len(strs) 5 | if lenstrs == 0: 6 | return '' 7 | if lenstrs == 1: 8 | return strs[0] 9 | 10 | d = {} 11 | s = len(strs[0]) 12 | for i in range(len(strs)): 13 | val = strs[i] 14 | lens = len(val) 15 | if lens < s: 16 | s = lens 17 | 18 | if lens not in d: 19 | d[lens] = [] 20 | 21 | d[lens].append(val) 22 | 23 | if s == 0: 24 | return '' 25 | # forEach from small to high 26 | search = d[s][0] 27 | for i in range(len(search), 0, -1): 28 | val = search[:i] 29 | isLongest = True 30 | for key in d: 31 | contain = self.contains(d[key], val) 32 | if not contain: 33 | isLongest = False 34 | break 35 | if isLongest: 36 | return val 37 | 38 | return '' 39 | 40 | def contains(self, strs, s): 41 | for i in range(len(strs)): 42 | val = strs[i] 43 | if val.find(s) != 0: 44 | return False 45 | 46 | return True 47 | 48 | 49 | 50 | s = Solution() 51 | assert s.longestCommonPrefix(['abcded', 'abcdef', 'abc', 'abc', 'abd']) == 'ab' 52 | assert s.longestCommonPrefix(['abcded', 'abcdef', 'abc', 'a', 'abd']) == 'a' 53 | assert s.longestCommonPrefix(['', 'abcdef', 'abc', 'a', 'abd']) == '' 54 | assert s.longestCommonPrefix(['mmm', 'abcdef', 'abc', 'a', 'abd']) == '' 55 | -------------------------------------------------------------------------------- /python/longest_palindromic_substring.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | # @return a string 3 | def longestPalindrome(self, s): 4 | lens = len(s) 5 | if (lens == 0): 6 | return 0 7 | 8 | maxLen = 1 9 | sIdx = 0 10 | 11 | for i in range(lens): 12 | # when increase 1 element, the maxLen can add 1, 2, 0 13 | # add 2, then compare s[i - maxLen -1] and i s[i - maxLen -1] 14 | if i - maxLen >=1 and s[i-maxLen - 1: i+1] == s[i-maxLen - 1: i +1][::-1]: 15 | sIdx = i - maxLen -1 16 | maxLen += 2 17 | # add 1, then compare s[i - maxLen] and i s[i - maxLen] 18 | elif i - maxLen >= 0 and s[i - maxLen :i + 1] == s[i - maxLen :i + 1][::-1]: 19 | sIdx = i - maxLen 20 | maxLen += 1 21 | 22 | return s[sIdx:sIdx + maxLen] 23 | 24 | 25 | 26 | # test 27 | 28 | s = Solution() 29 | 30 | print s.longestPalindrome('abcdedcba') 31 | assert s.longestPalindrome('abcdedcba') == 'abcdedcba' 32 | assert s.longestPalindrome('abcdedcbadddd') == 'abcdedcba' 33 | -------------------------------------------------------------------------------- /python/longest_substring_without_repeating_characters.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | # @return an integer 3 | def lengthOfLongestSubstring(self, s): 4 | d = {} 5 | lenS = len(s) 6 | 7 | if lenS <=1: 8 | return lenS 9 | 10 | ls = 0 11 | sls = 0 12 | sidx = 0 13 | for i in range(lenS): 14 | val = s[i] 15 | 16 | if val in d: 17 | d = self.clearD(d, s[sidx:d[val]]) 18 | sidx = d[val] + 1 19 | d[val] = i 20 | sls = len(d) 21 | else: 22 | sls = sls + 1 23 | d[val] = i 24 | 25 | ls = sls if sls > ls else ls 26 | 27 | return ls 28 | def clearD(self, d, s): 29 | for i in range(len(s)): 30 | del d[s[i]] 31 | 32 | return d 33 | 34 | 35 | 36 | s = Solution() 37 | 38 | assert s.lengthOfLongestSubstring('') == 0 39 | assert s.lengthOfLongestSubstring('ddddd') == 1 40 | assert s.lengthOfLongestSubstring('abcdefgab') == 7 41 | assert s.lengthOfLongestSubstring('abcdabcde') == 5 42 | 43 | 44 | -------------------------------------------------------------------------------- /python/lru_cache.py: -------------------------------------------------------------------------------- 1 | class LRUCache: 2 | 3 | # @param capacity, an integer 4 | def __init__(self, capacity): 5 | self.q = [] 6 | self.capacity = capacity; 7 | self.store = {} 8 | self.dbl = DBLinkedList() 9 | 10 | 11 | # @return an integer 12 | def get(self, key): 13 | if key in self.store: 14 | self.dbl.lift(self.store[key]) 15 | return self.store[key].value 16 | return -1 17 | 18 | 19 | # @param key, an integer 20 | # @param value, an integer 21 | # @return nothing 22 | def set(self, key, value): 23 | if key in self.store: 24 | n = self.store[key] 25 | n.value = value 26 | self.dbl.remove(n) 27 | self.dbl.append(n) 28 | else: 29 | if self.capacity == len(self.store): 30 | k = self.dbl.pop() 31 | del self.store[k] 32 | n = Node(key, value) 33 | self.dbl.append(n) 34 | self.store[key] = n 35 | 36 | 37 | class Node: 38 | def __init__(self, key, value): 39 | self.value = value 40 | self.key = key 41 | self.pre = None 42 | self.next = None 43 | 44 | class DBLinkedList: 45 | def __init__(self): 46 | self.head = Node(None, None) 47 | self.tail = Node(None, None) 48 | self.head.next = self.tail 49 | self.tail.pre = self.head 50 | 51 | def append(self, node): 52 | tmp = self.tail.pre 53 | tmp.next = node 54 | node.pre = tmp 55 | node.next = self.tail 56 | self.tail.pre = node 57 | def remove(self, node): 58 | node.pre.next = node.next 59 | node.next.pre = node.pre 60 | def pop(self): 61 | tmp = self.head.next 62 | self.head.next = tmp.next 63 | tmp.next.pre = self.head 64 | return tmp.key 65 | 66 | def lift(self, node): 67 | self.remove(node) 68 | self.append(node) 69 | 70 | 71 | s = LRUCache(3) 72 | s.set(1, 1) 73 | s.set(2, 2) 74 | s.set(3, 3) 75 | s.set(2, 4) 76 | s.set(4, 5) 77 | assert s.get(1) == -1 78 | assert s.get(2) == 4 79 | 80 | s = LRUCache(2) 81 | s.set(2,1) 82 | s.set(1,1) 83 | assert s.get(2) == 1 84 | s.set(4,1) 85 | assert s.get(1) == -1 86 | assert s.get(2) == 1 87 | 88 | s = LRUCache(1) 89 | s.set(2,1) 90 | assert s.get(2) == 1 91 | -------------------------------------------------------------------------------- /python/median_of_Two_Sorted_Arrays.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | # @return a float 3 | def findMedianSortedArrays(self, A, B): 4 | lenA = len(A) 5 | lenB = len(B) 6 | 7 | # the mid for both even and odd 8 | k = (lenA + lenB + 1)/2 9 | if (lenA + lenB)%2 == 1: 10 | return self.findK(A, B, k) 11 | else: 12 | return (self.findK(A, B, k) + self.findK(A, B, k + 1)) * 0.5 13 | 14 | # find the k-th smallest number 15 | def findK(self, A, B, k): 16 | lenA = len(A) 17 | lenB = len(B) 18 | 19 | # keep lenA <= lenB 20 | if (lenA > lenB): 21 | return self.findK(B, A, k) 22 | if (lenA == 0): 23 | return B[k-1] 24 | if (k == 1): 25 | return min(A[0], B[0]) 26 | 27 | # k/2 28 | # get the k smallest numbers in A+B 29 | midA = min(k/2, lenA) 30 | midB = k - midA 31 | 32 | if A [midA - 1] < B[midB - 1]: 33 | return self.findK(A[midA:], B, midB) 34 | else: 35 | return self.findK(A, B[midB:], midA) 36 | 37 | # tests 38 | s = Solution() 39 | assert s.findMedianSortedArrays([1,2,3,5], [2,5]) == 2.5 40 | assert s.findMedianSortedArrays([1,2,3,5], [2]) == 2 41 | assert s.findMedianSortedArrays([1,2,3,5], [8]) == 3 42 | assert s.findMedianSortedArrays([1,2], [1, 1]) == 1 43 | assert s.findMedianSortedArrays([2,3,4,5], [1]) == 3 44 | assert s.findMedianSortedArrays([2,3,4, 5, 6], [1]) == 3.5 45 | -------------------------------------------------------------------------------- /python/merge_two_sorted_lists.py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | # class ListNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.next = None 6 | 7 | class Solution: 8 | # @param two ListNodes 9 | # @return a ListNode 10 | def mergeTwoLists(self, l1, l2): 11 | if not l1: 12 | return l2 13 | if not l2: 14 | return l1 15 | 16 | 17 | s = ListNode(0) 18 | curr = s 19 | while l1 and l2: 20 | if l1.val < l2.val: 21 | val = l1.val 22 | l1 = l1.next 23 | else: 24 | val = l2.val 25 | l2 = l2.next 26 | curr.next = ListNode(val) 27 | curr = curr.next 28 | if l1: 29 | curr.next = l1 30 | if l2: 31 | curr.next = l2 32 | 33 | return s.next 34 | 35 | 36 | 37 | # # test code 38 | # class ListNode: 39 | # def __init__(self, x): 40 | # self.val = x 41 | # self.next = None 42 | # 43 | # def a2ll(l): 44 | # ll = ListNode(l[0]) 45 | # 46 | # cursor = ll 47 | # for i in range(1, len(l)): 48 | # cursor.next = ListNode(l[i]) 49 | # cursor = cursor.next 50 | # 51 | # return ll 52 | # def pl(ll): 53 | # while ll.next: 54 | # print ll.val, 55 | # ll = ll.next 56 | # print ll.val 57 | # 58 | # s = Solution() 59 | # ll = s.mergeTwoLists(a2ll([1,2,3,6,7]), a2ll([1,4,5,8])) 60 | # # output 1 1 2 3 4 5 6 7 8 61 | # pl(ll) 62 | -------------------------------------------------------------------------------- /python/palindrome_number.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | # @return a boolean 3 | def isPalindrome(self, x): 4 | if x < 0: 5 | return False 6 | if (x < 10): 7 | return True 8 | prefix = x 9 | suffix = x % 10 10 | p = 10 11 | # for 1213445443121 12 | # get x/10**n < 10**4 1213 and x%10**4 3121 13 | while suffix * suffix < x: 14 | 15 | prefix = x 16 | while prefix >= p: 17 | prefix = prefix / 10 18 | 19 | l = suffix / (p/10) 20 | h = prefix % 10 21 | if (l != h): 22 | return False 23 | p = p * 10 24 | suffix = x % p 25 | 26 | return True 27 | 28 | 29 | # test 30 | 31 | s = Solution() 32 | 33 | assert s.isPalindrome(10) == False 34 | assert s.isPalindrome(1) == True 35 | assert s.isPalindrome(-1) == False 36 | assert s.isPalindrome(1213) == False 37 | assert s.isPalindrome(12133121) == True 38 | assert s.isPalindrome(121313121) == True 39 | -------------------------------------------------------------------------------- /python/remove_duplicates_from_sorted_array.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | # @param a list of integers 3 | # @return an integer 4 | def removeDuplicates(self, A): 5 | # 1 1 2 2 2 2 3 4 5 6 | i = 0 7 | val = None 8 | while i < len(A): 9 | if val == A[i]: 10 | # A.pop(i) 11 | A[i-1:i+1] = [A[i-1]] 12 | else: 13 | val = A[i] 14 | i += 1 15 | 16 | print A 17 | return len(A) 18 | 19 | s = Solution() 20 | 21 | assert s.removeDuplicates([1,1,2,2,3,3,4,5,6]) == 6 22 | assert s.removeDuplicates([1,1]) == 1 23 | assert s.removeDuplicates([]) == 0 24 | -------------------------------------------------------------------------------- /python/remove_nth_node_from_end_of_list.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | # @return a ListNode 3 | def removeNthFromEnd(self, head, n): 4 | if n < 0 or head == None: 5 | return head 6 | 7 | d = {} 8 | d[0] = ListNode(0) 9 | d[0].next = head 10 | 11 | current = head 12 | # the length of the list 13 | lens = 1 14 | while current: 15 | d[lens] = current 16 | current = current.next 17 | lens += 1 18 | 19 | lens -= 1 20 | 21 | if n == 0: 22 | d[lens-1].next = None 23 | elif n <= lens: 24 | idx = lens - n + 1 25 | d[idx - 1].next = d[idx].next 26 | return d[0].next 27 | 28 | 29 | # test 30 | from _util import * 31 | s = Solution() 32 | r = s.removeNthFromEnd(a2ll([1,2]), 1) 33 | pl(r) 34 | -------------------------------------------------------------------------------- /python/reverse_integer.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | # @return an integer 3 | def reverse(self, x): 4 | maxint = 2**31 - 1 5 | sign = 1 6 | if x < 0: 7 | sign = -1 8 | strx = str(abs(x)) 9 | res = strx[::-1] 10 | if (int(res)) > maxint: 11 | return 0 12 | return sign*int(res) 13 | 14 | 15 | 16 | 17 | assert 1212 == 1212 18 | # test 19 | s = Solution() 20 | assert s.reverse(0) == 0 21 | assert s.reverse(100000) == 1 22 | assert s.reverse(1212) == 2121 23 | assert s.reverse(-899) == -998 24 | assert s.reverse(99989787387873**2) == 0 25 | -------------------------------------------------------------------------------- /python/string_to_integer_atoi.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | # @return an integer 3 | def atoi(self, str): 4 | str = str.lstrip(' ').rstrip(' '); 5 | 6 | if str == '': 7 | return 0 8 | 9 | sign = 1 10 | if str[0] == '-': 11 | sign = -1 12 | str = str[1:] 13 | elif str[0] == '+': 14 | str = str[1:] 15 | 16 | lens = len(str) 17 | if lens == 0: 18 | return 0 19 | 20 | 21 | s = '' 22 | for i in range(lens): 23 | if str[i].isdigit(): 24 | s = s + str[i] 25 | else: 26 | break 27 | 28 | if s == '': 29 | return 0 30 | 31 | res = sign * int(s) 32 | 33 | if res > 2147483647: 34 | return 2147483647 35 | elif res < -2147483648: 36 | return -2147483648 37 | else: 38 | return res 39 | 40 | 41 | s = Solution() 42 | 43 | assert s.atoi('') == 0 44 | assert s.atoi('aaa') == 0 45 | assert s.atoi('1213fa ') == 1213 46 | assert s.atoi('+1213fa') == 1213 47 | assert s.atoi('-1213fa') == -1213 48 | assert s.atoi('2147483648') == 2147483647 49 | assert s.atoi('+-2') == 0 50 | -------------------------------------------------------------------------------- /python/two-sum.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | # @return a tuple, (index1, index2) 3 | def twoSum(self, num, target): 4 | length = len(num) 5 | # use dict: value: index + 1 6 | # since there is only one solution, the right value must not be duplicated 7 | dic = {} 8 | for i in xrange(0, length): 9 | val = num[i] 10 | if (target - val) in dic: 11 | return (dic[target - val], i + 1) 12 | dic[val] = i + 1 13 | 14 | 15 | 16 | ## test code 17 | # num=[2, 7, 11, 15] 18 | # t= 26 19 | # s = Solution() 20 | # print s.twoSum(num, t) 21 | -------------------------------------------------------------------------------- /python/valid_parentheses.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | # @return a boolean 3 | def isValid(self, s): 4 | lens = len(s) 5 | if s == 0 or lens % 2 != 0: 6 | return False 7 | 8 | leftSets = set('{[(') 9 | rightSets = { 10 | ']': '[', 11 | '}': '{', 12 | ')': '(', 13 | } 14 | 15 | # check first char, avoid check range for stack[-1] later 16 | if s[0] not in leftSets: 17 | return False 18 | 19 | stack = [] 20 | for i in range(lens): 21 | val = s[i] 22 | if val in leftSets: 23 | stack.append(val) 24 | # pop corresponding parentheses of the stack 25 | elif val in rightSets and rightSets[val] == stack[len(stack) - 1]: 26 | stack.pop() 27 | else: 28 | return False 29 | 30 | # after the iteration, check whether the stack is empty 31 | if len(stack) != 0: 32 | return False 33 | return True 34 | 35 | s = Solution() 36 | assert s.isValid('[[[{{}}]]]') == True 37 | assert s.isValid('{}}') == False 38 | assert s.isValid('[[') == False 39 | assert s.isValid('][') == False 40 | -------------------------------------------------------------------------------- /python/zigzag_conversion.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | # @return a string 3 | def convert(self, s, nRows): 4 | 5 | if nRows == 1 or len(s) <= 2: 6 | return s 7 | 8 | # compute the length of the zigzag 9 | zigzagLen = 2*nRows - 2; 10 | lens = len(s) 11 | res = '' 12 | for i in range(nRows): 13 | idx = i 14 | while idx < lens: 15 | res = res + s[idx] 16 | if i != 0 and i != nRows - 1: 17 | x = idx + (zigzagLen - 2*i) 18 | if (x < lens): 19 | res = res + s[x] 20 | 21 | idx = idx + zigzagLen 22 | 23 | return res 24 | 25 | 26 | s = Solution() 27 | 28 | assert s.convert('0123456789', 5) == '0817926354' 29 | assert s.convert('0123456789', 3) == '0481357926' 30 | assert s.convert('0123456789', 2) == '0246813579' 31 | assert s.convert('012', 1) == '012' 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /tenth_line.bash: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | 3 | # sed version 4 | sed -n 10p file.txt 5 | -------------------------------------------------------------------------------- /valid_phone_numbers.bash: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | 3 | # Read from the file file.txt and output all valid phone numbers to stdout. 4 | # # first version, with while 5 | # while read num 6 | # do 7 | # if [[ "$num" =~ ^\([0-9]{3}\)\ [0-9]{3}-[0-9]{4}$ ]] || [[ "$num" =~ ^[0-9]{3}-[0-9]{3}-[0-9]{4}$ ]];then 8 | # echo $num 9 | # fi 10 | # done < file.txt 11 | 12 | # sed version 13 | 14 | # sed -nE '/^([0-9]{3}-|\([0-9]{3}\) )[0-9]{3}-[0-9]{4}$/p' file.txt 15 | 16 | # grep version 17 | grep -E '^(\([0-9]{3}\) |[0-9]{3}\-)[0-9]{3}\-[0-9]{4}$' file.txt 18 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | ajv@^6.12.3: 6 | version "6.12.6" 7 | resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" 8 | integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== 9 | dependencies: 10 | fast-deep-equal "^3.1.1" 11 | fast-json-stable-stringify "^2.0.0" 12 | json-schema-traverse "^0.4.1" 13 | uri-js "^4.2.2" 14 | 15 | ansi-regex@^2.0.0: 16 | version "2.1.1" 17 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" 18 | integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= 19 | 20 | ansi-styles@^2.2.1: 21 | version "2.2.1" 22 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" 23 | integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= 24 | 25 | asn1@~0.2.3: 26 | version "0.2.4" 27 | resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" 28 | integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== 29 | dependencies: 30 | safer-buffer "~2.1.0" 31 | 32 | assert-plus@1.0.0, assert-plus@^1.0.0: 33 | version "1.0.0" 34 | resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" 35 | integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= 36 | 37 | asynckit@^0.4.0: 38 | version "0.4.0" 39 | resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" 40 | integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= 41 | 42 | aws-sign2@~0.7.0: 43 | version "0.7.0" 44 | resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" 45 | integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= 46 | 47 | aws4@^1.8.0: 48 | version "1.11.0" 49 | resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" 50 | integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== 51 | 52 | bcrypt-pbkdf@^1.0.0: 53 | version "1.0.2" 54 | resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" 55 | integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= 56 | dependencies: 57 | tweetnacl "^0.14.3" 58 | 59 | camelcase@^6.2.0: 60 | version "6.2.0" 61 | resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809" 62 | integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== 63 | 64 | caseless@~0.12.0: 65 | version "0.12.0" 66 | resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" 67 | integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= 68 | 69 | chalk@^1.1.3: 70 | version "1.1.3" 71 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" 72 | integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= 73 | dependencies: 74 | ansi-styles "^2.2.1" 75 | escape-string-regexp "^1.0.2" 76 | has-ansi "^2.0.0" 77 | strip-ansi "^3.0.0" 78 | supports-color "^2.0.0" 79 | 80 | combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: 81 | version "1.0.8" 82 | resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" 83 | integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== 84 | dependencies: 85 | delayed-stream "~1.0.0" 86 | 87 | core-util-is@1.0.2: 88 | version "1.0.2" 89 | resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" 90 | integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= 91 | 92 | cross-fetch@^3.0.6: 93 | version "3.1.4" 94 | resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.4.tgz#9723f3a3a247bf8b89039f3a380a9244e8fa2f39" 95 | integrity sha512-1eAtFWdIubi6T4XPy6ei9iUFoKpUkIF971QLN8lIvvvwueI65+Nw5haMNKUwfJxabqlIIDODJKGrQ66gxC0PbQ== 96 | dependencies: 97 | node-fetch "2.6.1" 98 | 99 | dashdash@^1.12.0: 100 | version "1.14.1" 101 | resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" 102 | integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= 103 | dependencies: 104 | assert-plus "^1.0.0" 105 | 106 | delayed-stream@~1.0.0: 107 | version "1.0.0" 108 | resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" 109 | integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= 110 | 111 | ecc-jsbn@~0.1.1: 112 | version "0.1.2" 113 | resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" 114 | integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= 115 | dependencies: 116 | jsbn "~0.1.0" 117 | safer-buffer "^2.1.0" 118 | 119 | escape-string-regexp@^1.0.2: 120 | version "1.0.5" 121 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" 122 | integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= 123 | 124 | extend@~3.0.2: 125 | version "3.0.2" 126 | resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" 127 | integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== 128 | 129 | extract-files@^9.0.0: 130 | version "9.0.0" 131 | resolved "https://registry.yarnpkg.com/extract-files/-/extract-files-9.0.0.tgz#8a7744f2437f81f5ed3250ed9f1550de902fe54a" 132 | integrity sha512-CvdFfHkC95B4bBBk36hcEmvdR2awOdhhVUYH6S/zrVj3477zven/fJMYg7121h4T1xHZC+tetUpubpAhxwI7hQ== 133 | 134 | extsprintf@1.3.0: 135 | version "1.3.0" 136 | resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" 137 | integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= 138 | 139 | extsprintf@^1.2.0: 140 | version "1.4.0" 141 | resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" 142 | integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= 143 | 144 | fast-deep-equal@^3.1.1: 145 | version "3.1.3" 146 | resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" 147 | integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== 148 | 149 | fast-json-stable-stringify@^2.0.0: 150 | version "2.1.0" 151 | resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" 152 | integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== 153 | 154 | forever-agent@~0.6.1: 155 | version "0.6.1" 156 | resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" 157 | integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= 158 | 159 | form-data@^3.0.0: 160 | version "3.0.1" 161 | resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" 162 | integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== 163 | dependencies: 164 | asynckit "^0.4.0" 165 | combined-stream "^1.0.8" 166 | mime-types "^2.1.12" 167 | 168 | form-data@~2.3.2: 169 | version "2.3.3" 170 | resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" 171 | integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== 172 | dependencies: 173 | asynckit "^0.4.0" 174 | combined-stream "^1.0.6" 175 | mime-types "^2.1.12" 176 | 177 | getpass@^0.1.1: 178 | version "0.1.7" 179 | resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" 180 | integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= 181 | dependencies: 182 | assert-plus "^1.0.0" 183 | 184 | graphql-request@^3.4.0: 185 | version "3.4.0" 186 | resolved "https://registry.yarnpkg.com/graphql-request/-/graphql-request-3.4.0.tgz#3a400cd5511eb3c064b1873afb059196bbea9c2b" 187 | integrity sha512-acrTzidSlwAj8wBNO7Q/UQHS8T+z5qRGquCQRv9J1InwR01BBWV9ObnoE+JS5nCCEj8wSGS0yrDXVDoRiKZuOg== 188 | dependencies: 189 | cross-fetch "^3.0.6" 190 | extract-files "^9.0.0" 191 | form-data "^3.0.0" 192 | 193 | graphql@^15.5.0: 194 | version "15.5.0" 195 | resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.5.0.tgz#39d19494dbe69d1ea719915b578bf920344a69d5" 196 | integrity sha512-OmaM7y0kaK31NKG31q4YbD2beNYa6jBBKtMFT6gLYJljHLJr42IqJ8KX08u3Li/0ifzTU5HjmoOOrwa5BRLeDA== 197 | 198 | har-schema@^2.0.0: 199 | version "2.0.0" 200 | resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" 201 | integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= 202 | 203 | har-validator@~5.1.3: 204 | version "5.1.5" 205 | resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" 206 | integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== 207 | dependencies: 208 | ajv "^6.12.3" 209 | har-schema "^2.0.0" 210 | 211 | has-ansi@^2.0.0: 212 | version "2.0.0" 213 | resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" 214 | integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= 215 | dependencies: 216 | ansi-regex "^2.0.0" 217 | 218 | http-signature@~1.2.0: 219 | version "1.2.0" 220 | resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" 221 | integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= 222 | dependencies: 223 | assert-plus "^1.0.0" 224 | jsprim "^1.2.2" 225 | sshpk "^1.7.0" 226 | 227 | is-typedarray@~1.0.0: 228 | version "1.0.0" 229 | resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" 230 | integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= 231 | 232 | isstream@~0.1.2: 233 | version "0.1.2" 234 | resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" 235 | integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= 236 | 237 | jsbn@~0.1.0: 238 | version "0.1.1" 239 | resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" 240 | integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= 241 | 242 | json-schema-traverse@^0.4.1: 243 | version "0.4.1" 244 | resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" 245 | integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== 246 | 247 | json-schema@0.2.3: 248 | version "0.2.3" 249 | resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" 250 | integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= 251 | 252 | json-stringify-safe@~5.0.1: 253 | version "5.0.1" 254 | resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" 255 | integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= 256 | 257 | jsprim@^1.2.2: 258 | version "1.4.1" 259 | resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" 260 | integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= 261 | dependencies: 262 | assert-plus "1.0.0" 263 | extsprintf "1.3.0" 264 | json-schema "0.2.3" 265 | verror "1.10.0" 266 | 267 | leetcode@^1.2.0: 268 | version "1.2.0" 269 | resolved "https://registry.yarnpkg.com/leetcode/-/leetcode-1.2.0.tgz#0fec69246035e43b4637dc88dfe86af9c193623e" 270 | integrity sha1-D+xpJGA15DtGN9yI3+hq+cGTYj4= 271 | 272 | mime-db@1.47.0: 273 | version "1.47.0" 274 | resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.47.0.tgz#8cb313e59965d3c05cfbf898915a267af46a335c" 275 | integrity sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw== 276 | 277 | mime-types@^2.1.12, mime-types@~2.1.19: 278 | version "2.1.30" 279 | resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.30.tgz#6e7be8b4c479825f85ed6326695db73f9305d62d" 280 | integrity sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg== 281 | dependencies: 282 | mime-db "1.47.0" 283 | 284 | minimist@^1.2.5: 285 | version "1.2.5" 286 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" 287 | integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== 288 | 289 | mkdirp@^0.5.1: 290 | version "0.5.5" 291 | resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" 292 | integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== 293 | dependencies: 294 | minimist "^1.2.5" 295 | 296 | node-fetch@2.6.1: 297 | version "2.6.1" 298 | resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" 299 | integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== 300 | 301 | oauth-sign@~0.9.0: 302 | version "0.9.0" 303 | resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" 304 | integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== 305 | 306 | performance-now@^2.1.0: 307 | version "2.1.0" 308 | resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" 309 | integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= 310 | 311 | psl@^1.1.28: 312 | version "1.8.0" 313 | resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" 314 | integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== 315 | 316 | punycode@^2.1.0, punycode@^2.1.1: 317 | version "2.1.1" 318 | resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" 319 | integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== 320 | 321 | qs@~6.5.2: 322 | version "6.5.2" 323 | resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" 324 | integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== 325 | 326 | request@^2.73.0: 327 | version "2.88.2" 328 | resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" 329 | integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== 330 | dependencies: 331 | aws-sign2 "~0.7.0" 332 | aws4 "^1.8.0" 333 | caseless "~0.12.0" 334 | combined-stream "~1.0.6" 335 | extend "~3.0.2" 336 | forever-agent "~0.6.1" 337 | form-data "~2.3.2" 338 | har-validator "~5.1.3" 339 | http-signature "~1.2.0" 340 | is-typedarray "~1.0.0" 341 | isstream "~0.1.2" 342 | json-stringify-safe "~5.0.1" 343 | mime-types "~2.1.19" 344 | oauth-sign "~0.9.0" 345 | performance-now "^2.1.0" 346 | qs "~6.5.2" 347 | safe-buffer "^5.1.2" 348 | tough-cookie "~2.5.0" 349 | tunnel-agent "^0.6.0" 350 | uuid "^3.3.2" 351 | 352 | safe-buffer@^5.0.1, safe-buffer@^5.1.2: 353 | version "5.2.1" 354 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" 355 | integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== 356 | 357 | safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: 358 | version "2.1.2" 359 | resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" 360 | integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== 361 | 362 | sshpk@^1.7.0: 363 | version "1.16.1" 364 | resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" 365 | integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== 366 | dependencies: 367 | asn1 "~0.2.3" 368 | assert-plus "^1.0.0" 369 | bcrypt-pbkdf "^1.0.0" 370 | dashdash "^1.12.0" 371 | ecc-jsbn "~0.1.1" 372 | getpass "^0.1.1" 373 | jsbn "~0.1.0" 374 | safer-buffer "^2.0.2" 375 | tweetnacl "~0.14.0" 376 | 377 | strip-ansi@^3.0.0: 378 | version "3.0.1" 379 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" 380 | integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= 381 | dependencies: 382 | ansi-regex "^2.0.0" 383 | 384 | supports-color@^2.0.0: 385 | version "2.0.0" 386 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" 387 | integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= 388 | 389 | tough-cookie@~2.5.0: 390 | version "2.5.0" 391 | resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" 392 | integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== 393 | dependencies: 394 | psl "^1.1.28" 395 | punycode "^2.1.1" 396 | 397 | tunnel-agent@^0.6.0: 398 | version "0.6.0" 399 | resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" 400 | integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= 401 | dependencies: 402 | safe-buffer "^5.0.1" 403 | 404 | tweetnacl@^0.14.3, tweetnacl@~0.14.0: 405 | version "0.14.5" 406 | resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" 407 | integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= 408 | 409 | uri-js@^4.2.2: 410 | version "4.4.1" 411 | resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" 412 | integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== 413 | dependencies: 414 | punycode "^2.1.0" 415 | 416 | uuid@^3.3.2: 417 | version "3.4.0" 418 | resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" 419 | integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== 420 | 421 | verror@1.10.0: 422 | version "1.10.0" 423 | resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" 424 | integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= 425 | dependencies: 426 | assert-plus "^1.0.0" 427 | core-util-is "1.0.2" 428 | extsprintf "^1.2.0" 429 | --------------------------------------------------------------------------------