├── README.md ├── 026.Remove Duplicates from Sorted Array.js ├── 104.Maximum Depth of Binary Tree.js ├── 125.Valid Palindrome.js ├── 171.Excel Sheet Column Number.js ├── 167.Two Sum II - Input array is sorted.js ├── 013.Roman-To-Integer.js ├── 206.Reverse Linked List.js ├── 001.Two-Sum.js ├── 008.String to Integer (atoi).js ├── 189.Rotate Array.js ├── 121.Best Time to Buy and Sell Stock.js ├── 003.Longest-Substring-Without-Repeating-Characters.js ├── 202.Happy Number.js ├── 278.First Bad Version.js ├── 266.Permutation-Palindrome.js ├── 186.Reverse Words in a String II.js ├── 290.Word-Pattern.js ├── 002.Add-Two-Numbers.js ├── 146.LRU Cache.js ├── 049.Group Anagrams.js ├── 010.Regular Expression Matching.js ├── 004.Median of Two Sorted Arrays.js ├── 036.Valid Sudoku.js ├── 017.Letter Combinations of a Phone Number.js ├── 102.Binary Tree Level Order Traversal.js ├── 155.Min Stack.js ├── 138.Copy List with Random Pointer.js ├── 161.One Edit Distance.js ├── 078.Subsets.js ├── 023.Merge k Sorted Lists.js ├── 033.Search in Rotated Sorted Array.js ├── 140.Word Break II.js ├── 291.Word-Pattern-II.js └── 208.Implement Trie (Prefix Tree).js /README.md: -------------------------------------------------------------------------------- 1 | # Leetcode Javascript 2 | 3 | Solutions to Leetcode challenges in JavaScript 4 | 5 | [Leetcode - All solutions (Python)](https://github.com/csujedihy/lc-all-solutions) 6 | -------------------------------------------------------------------------------- /026.Remove Duplicates from Sorted Array.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @return {number} 4 | */ 5 | var removeDuplicates = function (A) { 6 | if (A === null) { 7 | return 0; 8 | } 9 | 10 | var index = 1; 11 | 12 | while (index < A.length) { 13 | if (A[index] === A[index - 1]) { 14 | A.splice(index, 1); 15 | } else { 16 | index++; 17 | } 18 | } 19 | 20 | return A.length; 21 | }; -------------------------------------------------------------------------------- /104.Maximum Depth of Binary 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} root 10 | * @return {number} 11 | * 12 | * Your runtime beats 94.47% of javascriptsubmissions. 13 | */ 14 | var maxDepth = function (root) { 15 | if (root === null) { 16 | return 0; 17 | } 18 | 19 | return 1 + Math.max(maxDepth(root.left), maxDepth(root.right)); 20 | }; -------------------------------------------------------------------------------- /125.Valid Palindrome.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} s 3 | * @return {boolean} 4 | * 5 | * Your runtime beats 94.49% of javascriptsubmissions. 6 | */ 7 | var isPalindrome = function (s) { 8 | // Removes non alphanumeric characters from the string. 9 | s = s.replace(/\W/g, ''); 10 | if (s === '') { 11 | return true; 12 | } 13 | 14 | s = s.toLowerCase(); 15 | for (var i = 0, j = s.length - 1; i < j; i++, j--) { 16 | if (s.charAt(i) !== s.charAt(j)) { 17 | return false; 18 | } 19 | } 20 | return true; 21 | }; -------------------------------------------------------------------------------- /171.Excel Sheet Column Number.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} s 3 | * @return {number} 4 | * 5 | * Your runtime beats 91.49% of javascriptsubmissions. 6 | */ 7 | var titleToNumber = function(s) { 8 | var alphabets = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; 9 | var colNum = 0; 10 | var tempCol; 11 | 12 | var sArr = s.split(''); 13 | var totalChars = s.length; 14 | 15 | while(sArr.length > 0) { 16 | tempCol = alphabets.indexOf(sArr[sArr.length - 1]) + 1; 17 | colNum += tempCol * Math.pow(26, totalChars - sArr.length); 18 | sArr.pop(); 19 | } 20 | 21 | return colNum; 22 | }; -------------------------------------------------------------------------------- /167.Two Sum II - Input array is sorted.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} numbers 3 | * @param {number} target 4 | * @return {number[]} 5 | */ 6 | var twoSum = function (numbers, target) { 7 | var map = {}; 8 | var val; 9 | var remainder; 10 | var result = []; 11 | 12 | for (var i = 0; i < numbers.length; i++) { 13 | val = numbers[i]; 14 | remainder = target - val; 15 | if (map[remainder] !== undefined) { 16 | result.push(map[remainder] + 1); 17 | result.push(i + 1); 18 | break; 19 | } else { 20 | map[val] = i; 21 | } 22 | } 23 | return result; 24 | }; -------------------------------------------------------------------------------- /013.Roman-To-Integer.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} s 3 | * @return {number} 4 | * 5 | * Your runtime beats 89.30% of javascript submissions. 6 | */ 7 | var romanToInt = function (s) { 8 | var key = { 9 | M: 1000, 10 | D: 500, 11 | C: 100, 12 | L: 50, 13 | X: 10, 14 | V: 5, 15 | I: 1 16 | }; 17 | 18 | var result = 0; 19 | var romanArray = s.split(''); 20 | var prevVal = romanArray[0]; 21 | 22 | romanArray.forEach(function (char) { 23 | var val = key[char]; 24 | result += (prevVal < val) ? val - 2 * prevVal : val; 25 | prevVal = val; 26 | }); 27 | return result; 28 | }; -------------------------------------------------------------------------------- /206.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 | * Your runtime beats 94.95% of javascriptsubmissions. 13 | */ 14 | var reverseList = function (head) { 15 | if (head === null) return null; 16 | 17 | var node = head; 18 | while (node.next !== null) { 19 | var newHead = node.next; 20 | node.next = newHead.next; 21 | 22 | newHead.next = head; 23 | head = newHead; 24 | } 25 | 26 | return head; 27 | }; -------------------------------------------------------------------------------- /001.Two-Sum.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @param {number} target 4 | * @return {number[]} 5 | * 6 | * Runtime beats 84.88% of javascript submissions 7 | */ 8 | var twoSum = function (nums, target) { 9 | var val, 10 | neededVal, 11 | len = nums.length, 12 | mappings = {}, 13 | result = []; 14 | 15 | for (var i = 0; i < len; i++) { 16 | val = nums[i]; 17 | neededVal = target - val; 18 | if (neededVal in mappings) { 19 | result.push(mappings[neededVal] + 1); 20 | result.push(i + 1); 21 | break; 22 | } else { 23 | mappings[val] = i; 24 | } 25 | } 26 | 27 | return result; 28 | }; -------------------------------------------------------------------------------- /008.String to Integer (atoi).js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} str 3 | * @return {number} 4 | * 5 | * Your runtime beats 100.00% of javascriptsubmissions. 6 | */ 7 | 8 | var myAtoi = function(str) { 9 | 10 | var val = parseInt(str); 11 | if(str === null || str.length === 0 || isNaN(val)){ 12 | return 0; 13 | } 14 | 15 | var maxNegInt = -Math.pow(2,31); // Maybe use Number.MAX_SAFE_INTEGER ? 16 | var maxInt = Math.pow(2,31) - 1; // Maybe use Number.MIN_SAFE_INTEGER ? 17 | 18 | if(val > 0 && val > maxInt){ 19 | return maxInt; 20 | } 21 | 22 | if(val < 0 && val < maxNegInt){ 23 | return maxNegInt; 24 | } 25 | 26 | return val; 27 | }; -------------------------------------------------------------------------------- /189.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 | 7 | var rotate = function (nums, k) { 8 | k = k % nums.length; 9 | 10 | nums.reverse(); 11 | nums.reverseFromLToR(0, k - 1); 12 | nums.reverseFromLToR(k, nums.length - 1); 13 | }; 14 | 15 | Array.prototype.reverseFromLToR = function (left, right) { 16 | if (right >= this.length) { 17 | return; 18 | } 19 | 20 | while (left < right) { 21 | var temp = this[left]; 22 | this[left] = this[right]; 23 | this[right] = temp; 24 | left++; 25 | right--; 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /121.Best Time to Buy and Sell Stock.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} prices 3 | * @return {number} 4 | * 5 | * Your runtime beats 86.41% of javascriptsubmissions. 6 | */ 7 | var maxProfit = function (prices) { 8 | if (prices === null || prices.length === 0) { 9 | return 0; 10 | } 11 | 12 | var min; 13 | var max; 14 | var diff = 0; 15 | 16 | for (var i = 0; i < prices.length; i++) { 17 | var price = prices[i]; 18 | if (price < min || min == undefined) { 19 | min = price; 20 | } 21 | 22 | diff = price - min; 23 | 24 | if (diff > max || max === undefined) { 25 | max = diff; 26 | } 27 | } 28 | 29 | return max; 30 | }; -------------------------------------------------------------------------------- /003.Longest-Substring-Without-Repeating-Characters.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} s 3 | * @return {number} 4 | * 5 | * Runtime beats 72.93% of javascript submissions. 6 | */ 7 | var lengthOfLongestSubstring = function (s) { 8 | if (!s) { return 0; } 9 | var map = []; 10 | var len = 0; 11 | var start = 0; 12 | var maxlen = len; 13 | 14 | for (var i = 0; i < s.length; i++) { 15 | var currChar = s[i]; 16 | if (map[currChar] !== undefined && map[currChar] >= start) { 17 | start = map[currChar] + 1; 18 | len = i - start; 19 | } 20 | 21 | len++; 22 | 23 | if (len > maxlen) { 24 | maxlen = len; 25 | } 26 | 27 | map[currChar] = i; 28 | } 29 | return maxlen; 30 | }; 31 | -------------------------------------------------------------------------------- /202.Happy Number.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number} n 3 | * @return {boolean} 4 | * 5 | * Your runtime beats 90.58% of javascriptsubmissions. 6 | */ 7 | var isHappy = function (n) { 8 | if (n === null) { 9 | return false; 10 | } 11 | 12 | var val = n; 13 | var hash = {}; 14 | 15 | // Check to make sure the total hasn't been visited yet. 16 | // Or else it will cause and infinite loop. 17 | while (!hash[val]) { 18 | if (val === 1) { 19 | return true; 20 | } 21 | 22 | hash[val] = true; 23 | var sarr = val.toString().split(''); 24 | 25 | val = sarr.reduce(function (sum, digit) { 26 | sum += Math.pow(parseInt(digit, 10), 2); 27 | return sum; 28 | }, 0); 29 | } 30 | 31 | return false; 32 | }; -------------------------------------------------------------------------------- /278.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 lt = 1; 22 | var rt = n; 23 | var m, bad; 24 | while (lt <= rt) { 25 | m = parseInt((lt + rt) / 2, 10); 26 | //console.log(m); 27 | if (isBadVersion(m)) { 28 | bad = m; 29 | rt = m - 1; 30 | } else { 31 | lt = m + 1; 32 | } 33 | } 34 | return bad; 35 | }; 36 | }; -------------------------------------------------------------------------------- /266.Permutation-Palindrome.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} s 3 | * @return {boolean} 4 | * 5 | * Your runtime beats 84.21% of javascriptsubmissions. 6 | */ 7 | var canPermutePalindrome = function (word) { 8 | var charCounts = mapCharCounts(word); 9 | var numOfOddCharCounts = 0; 10 | 11 | for (var currChar in charCounts) { 12 | if (charCounts.hasOwnProperty(currChar)) { 13 | if (charCounts[currChar] % 2 !== 0) { 14 | numOfOddCharCounts++; 15 | if (numOfOddCharCounts > 1) { 16 | return false; 17 | } 18 | } 19 | } 20 | } 21 | 22 | function mapCharCounts(str) { 23 | var charCounts = {}; 24 | for (var i = 0; i < str.length; i++) { 25 | var char = str.charAt(i); 26 | charCounts[char] = charCounts[char] + 1 || 1; 27 | } 28 | return charCounts; 29 | } 30 | 31 | return true; 32 | }; -------------------------------------------------------------------------------- /186.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 | // Quick JS way 7 | var reverseWords = function (str) { 8 | if (str === null || str === undefined) return null; 9 | 10 | return str.trim().split(/\s+/).reverse().join(' '); 11 | }; 12 | 13 | // Algorithmic way 14 | var reverseWords = function (str) { 15 | if (str === null || str === undefined) return null; 16 | 17 | var reversed = '', 18 | inWord = false, 19 | word = ''; 20 | 21 | for (var i = 0; i < str.length; i++) { 22 | if (str[i] === ' ') { 23 | if (inWord) { 24 | inWord = false; 25 | 26 | reversed = word + (reversed === '' ? '' : ' ') + reversed; 27 | 28 | word = ''; 29 | } 30 | } else { 31 | inWord = true; 32 | word += str[i] 33 | } 34 | } 35 | 36 | if (inWord) { 37 | inWord = false; 38 | reversed = word + (reversed === '' ? '' : ' ') + reversed; 39 | } 40 | 41 | return reversed; 42 | }; 43 | -------------------------------------------------------------------------------- /290.Word-Pattern.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} pattern 3 | * @param {string} str 4 | * @return {boolean} 5 | * 6 | * Runtime beats 60.00% of javascript submissions. 7 | */ 8 | var wordPattern = function (pattern, str) { 9 | var patternBlocks = pattern.split(''); 10 | var strBlocks = str.split(' '); 11 | 12 | if (patternBlocks.length !== strBlocks.length) { 13 | return false; 14 | } 15 | 16 | var cache1 = {}; 17 | var cache2 = {}; 18 | var patternChunk; 19 | var strChunk; 20 | 21 | for (var i = 0; i < pattern.length; i++) { 22 | patternChunk = patternBlocks[i]; 23 | strChunk = strBlocks[i]; 24 | 25 | if (cache1[patternChunk] === undefined) { 26 | cache1[patternChunk] = strChunk; 27 | 28 | if (cache2[strChunk] === undefined) { 29 | cache2[strChunk] = patternChunk; 30 | } else { 31 | if (cache2[strChunk] !== patternChunk) { 32 | return false; 33 | } 34 | } 35 | } else { 36 | if (cache1[patternChunk] !== strChunk) { 37 | return false; 38 | } 39 | } 40 | } 41 | return true; 42 | }; -------------------------------------------------------------------------------- /002.Add-Two-Numbers.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} l1 10 | * @param {ListNode} l2 11 | * @return {ListNode} 12 | * 13 | * Runtime beats 75.81% of javascript submissions. 14 | */ 15 | var addTwoNumbers = function (l1, l2) { 16 | if (l1 === null || l2 === null) { 17 | return l1 || l2; 18 | } 19 | 20 | //Instantiate a ListNode here, with head.next as header, pos as a pointer points to current position 21 | var head = new ListNode(0); 22 | var pos = head; 23 | var temp = 0; 24 | while (l2 !== null || l1 !== null || temp > 0) { 25 | 26 | //(l2!==null || l1!==null || temp>0) indicates that next digit is not null, so instantiate a Node and move to it 27 | pos.next = new ListNode(0); 28 | pos = pos.next; 29 | 30 | if (l1 !== null) { 31 | temp += l1.val; 32 | l1 = l1.next; 33 | } 34 | if (l2 !== null) { 35 | temp += l2.val; 36 | l2 = l2.next; 37 | } 38 | 39 | pos.val = temp % 10; 40 | temp = parseInt(temp / 10, 10); 41 | } 42 | return head.next; 43 | }; -------------------------------------------------------------------------------- /146.LRU Cache.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @constructor 3 | * 4 | * Your runtime beats 91.18% of javascriptsubmissions. 5 | */ 6 | var LRUCache = function (capacity) { 7 | this.capacity = capacity; 8 | this.currentCapacity = 0; 9 | this.queue = []; 10 | this.cache = {}; 11 | }; 12 | 13 | /** 14 | * @param {number} key 15 | * @returns {number} 16 | */ 17 | LRUCache.prototype.get = function (key) { 18 | if (this.cache[key] !== undefined) { 19 | this.queue.splice(this.queue.indexOf(key), 1); 20 | this.queue.push(key); 21 | return this.cache[key]; 22 | } else { 23 | return -1; 24 | } 25 | }; 26 | 27 | /** 28 | * @param {number} key 29 | * @param {number} value 30 | * @returns {void} 31 | */ 32 | LRUCache.prototype.set = function (key, value) { 33 | if (key === undefined || value === undefined) return; 34 | 35 | if (this.cache[key] !== undefined) { 36 | this.queue.splice(this.queue.indexOf(key), 1); 37 | this.currentCapacity--; 38 | } else if (this.capacity === this.currentCapacity) { 39 | this.currentCapacity--; 40 | this.cache[this.queue.shift()] = undefined; 41 | } 42 | 43 | this.currentCapacity++; 44 | this.queue.push(key); 45 | this.cache[key] = value; 46 | }; 47 | -------------------------------------------------------------------------------- /049.Group Anagrams.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string[]} strs 3 | * @return {string[][]} 4 | * 5 | * Your runtime beats 94.87% of javascriptsubmissions. 6 | */ 7 | var groupAnagrams = function (strs) { 8 | if (!strs || strs.length === 0) { 9 | return []; 10 | } 11 | if (strs.length === 1) { 12 | return [strs]; 13 | } 14 | 15 | var map = {}, 16 | key; 17 | 18 | strs.forEach(function (str, i) { 19 | key = str.split('').sort().join(''); 20 | if (map[key] === undefined) { 21 | map[key] = []; 22 | } 23 | 24 | insert(map[key], str); 25 | // OR 26 | // map[key].push(str); 27 | // map[key].sort(); 28 | }); 29 | 30 | return Object.keys(map).reduce(function (result, key) { 31 | result.push(map[key]); 32 | return result; 33 | }, []); 34 | }; 35 | 36 | 37 | function insert(arr, item) { 38 | if (arr.length === 0) { 39 | arr.push(item); 40 | } else { 41 | // Insert element into array (in lexicographic/alphabetical order) 42 | var i = arr.length - 1; 43 | for (; i >= 0; i--) { 44 | if (i === 0 && arr[i] > item) { 45 | arr.unshift(item); 46 | break; 47 | } else if (arr[i] <= item) { 48 | arr.splice(i + 1, 0, item); 49 | break; 50 | } 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /010.Regular Expression Matching.js: -------------------------------------------------------------------------------- 1 | /** 2 | * '.' Matches any single character. 3 | * '*' Matches zero or more of the preceding element. 4 | * The matching should cover the entire input string (not partial). 5 | * 6 | * The function prototype should be: bool isMatch(const char *s, const char *p) 7 | * 8 | * Some examples: 9 | * isMatch("aa","a") → false 10 | * isMatch("aa","aa") → true 11 | * isMatch("aaa","aa") → false 12 | * isMatch("aa", "a*") → true 13 | * isMatch("aa", ".*") → true 14 | * isMatch("ab", ".*") → true 15 | * isMatch("aab", "c*a*b") → true 16 | * 17 | * @param {string} s 18 | * @param {string} p 19 | * @return {boolean} 20 | */ 21 | 22 | var isMatch = function (s, p) { 23 | if (p.length === 0) { 24 | return s.length === 0; 25 | } 26 | 27 | // p's length 1 is special case 28 | if (p.length === 1 || p[1] !== '*') { 29 | if (s.length < 1 || (p[0] !== '.' && s[0] !== p[0])) { 30 | return false; 31 | } 32 | return isMatch(s.slice(1), p.slice(1)); 33 | } else { 34 | var len = s.length; 35 | var i = -1; 36 | while (i < len && (i < 0 || p[0] === '.' || p[0] === s[i])) { 37 | if (isMatch(s.slice(i + 1), p.slice(2))) { 38 | return true; 39 | } 40 | i++; 41 | } 42 | return false; 43 | } 44 | }; -------------------------------------------------------------------------------- /004.Median of Two Sorted Arrays.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums1 3 | * @param {number[]} nums2 4 | * @return {number} 5 | * 6 | * Your runtime beats 89.47% of javascriptsubmissions. 7 | */ 8 | 9 | var findMedianSortedArrays = function (nums1, nums2) { 10 | var len1 = nums1.length; 11 | var len2 = nums2.length; 12 | 13 | if (len1 === 0 && len2 === 0) return null; 14 | 15 | var mid = Math.floor((len1 + len2) / 2); 16 | 17 | var m1 = kth(nums1, len1, nums2, len2, mid + 1); 18 | 19 | if ((len1 + len2) % 2 === 0) { 20 | return (m1 + kth(nums1, len1, nums2, len2, mid)) / 2; 21 | } 22 | 23 | return m1; 24 | }; 25 | 26 | function kth(a, la, b, lb, k) { 27 | if (lb > la) return kth(b, lb, a, la, k); 28 | if (lb === 0) return a[k - 1]; 29 | if (k === 1) return Math.min(a[0], b[0]); 30 | 31 | // divide into two parts 32 | var j = Math.min(lb, Math.floor(k / 2)); 33 | // # of elements smaller than a[i-1] plus # of elements smaller than b[j-1] === k 34 | var i = k - j; 35 | 36 | // the smaller one guarantees that elements in the left of which are smaller than the kth element 37 | if (a[i - 1] > b[j - 1]) 38 | // find (k-j)th smallest element in array (b+j) 39 | return kth(a, i, b.slice(j), lb - j, k - j); 40 | 41 | // find (k-i)th smallest element in array (a+i) 42 | return kth(a.slice(i), la - i, b, j, k - i); 43 | } -------------------------------------------------------------------------------- /036.Valid Sudoku.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {character[][]} board 3 | * @return {boolean} 4 | * 5 | * Your runtime beats 86.67% of javascriptsubmissions. 6 | */ 7 | var isValidSudoku = function (board) { 8 | var dupCheck; 9 | // col 10 | for (var i = 0; i < board.length; i++) { 11 | dupCheck = {}; 12 | 13 | for (var j = 0; j < board[0].length; j++) { 14 | if (board[i][j] !== '.' && dupCheck[board[i][j]]) { 15 | return false; 16 | } else { 17 | dupCheck[board[i][j]] = true; 18 | } 19 | } 20 | } 21 | // row 22 | for (i = 0; i < board.length; i++) { 23 | dupCheck = {}; 24 | 25 | for (j = 0; j < board[0].length; j++) { 26 | if (board[j][i] !== '.' && dupCheck[board[j][i]]) { 27 | return false; 28 | } else { 29 | dupCheck[board[j][i]] = true; 30 | } 31 | } 32 | } 33 | // 9 x 9 blocks 34 | for (i = 0; i < board.length; i += 3) { 35 | for (j = 0; j < board.length; j += 3) { 36 | dupCheck = {}; 37 | 38 | for (var x = 0; x < 3; x++) { 39 | for (var y = 0; y < 3; y++) { 40 | if (board[i + x][j + y] !== '.' && dupCheck[board[i + x][j + y]]) { 41 | return false; 42 | } else { 43 | dupCheck[board[i + x][j + y]] = true; 44 | } 45 | } 46 | } 47 | } 48 | } 49 | 50 | return true; 51 | }; -------------------------------------------------------------------------------- /017.Letter Combinations of a Phone Number.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} digits 3 | * @return {string[]} 4 | * 5 | * Your runtime beats 93.33% of javascriptsubmissions. 6 | */ 7 | var letterCombinations = function (digits) { 8 | var result = []; 9 | 10 | if (digits === null || digits.length === 0) { 11 | return result; 12 | } 13 | 14 | var str = []; 15 | 16 | generate(digits, 0, str, result); 17 | return result; 18 | }; 19 | 20 | var generate = function (digits, depth, str, result) { 21 | if (digits.length === depth) { 22 | result.push(str.join('')); 23 | return; 24 | } 25 | 26 | var letters = convertDigitToLetters(digits[depth]); 27 | 28 | for (var i = 0; i < letters.length; i++) { 29 | var letter = letters[i]; 30 | str.push(letter); 31 | generate(digits, depth + 1, str, result); 32 | str.pop(); 33 | } 34 | }; 35 | 36 | var convertDigitToLetters = function (digit) { 37 | switch (digit) { 38 | case '1': 39 | return ''; 40 | case '2': 41 | return 'abc'; 42 | case '3': 43 | return 'def'; 44 | case '4': 45 | return 'ghi'; 46 | case '5': 47 | return 'jkl'; 48 | case '6': 49 | return 'mno'; 50 | case '7': 51 | return 'pqrs'; 52 | case '8': 53 | return 'tuv'; 54 | case '9': 55 | return 'wxyz'; 56 | case '0': 57 | return ' '; 58 | } 59 | }; -------------------------------------------------------------------------------- /102.Binary Tree Level Order Traversal.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 | * @return {number[][]} 11 | * 12 | * Your runtime beats 88.57% of javascriptsubmissions. 13 | */ 14 | var levelOrder = function (root) { 15 | var result = []; 16 | 17 | if (root === null) { 18 | return result; 19 | } 20 | 21 | var queue = []; 22 | var temp = []; 23 | var currLevelCount = 1; // Since there is only one node in the root level. 24 | var nextLevelCount = 0; 25 | 26 | queue.push(root); 27 | 28 | while (queue.length !== 0) { 29 | var p = queue.shift(); 30 | temp.push(p.val); 31 | currLevelCount--; // decrease count after pushing to temp. 32 | 33 | if (p.left) { 34 | queue.push(p.left); 35 | nextLevelCount++; // increase count for every new node. 36 | } 37 | 38 | if (p.right) { 39 | queue.push(p.right); 40 | nextLevelCount++; // increase count for every new node. 41 | } 42 | 43 | if (currLevelCount === 0) { 44 | // All nodes in current level have been visited 45 | result.push(temp); 46 | currLevelCount = nextLevelCount; 47 | nextLevelCount = 0; 48 | temp = []; // reset temp. 49 | } 50 | } 51 | return result; 52 | }; -------------------------------------------------------------------------------- /155.Min Stack.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Design a stack that supports push, pop, top, and retrieving the minimum element in constant time. 3 | * 4 | * push(x) -- Push element x onto stack. 5 | * pop() -- Removes the element on top of the stack. 6 | * top() -- Get the top element. 7 | * getMin() -- Retrieve the minimum element in the stack. 8 | * 9 | * Your runtime beats 96.43% of javascriptsubmissions. 10 | */ 11 | var MinStack = function () { 12 | this.min = []; 13 | this.stack = []; 14 | }; 15 | 16 | /** 17 | * @param {number} x 18 | * @returns {void} 19 | */ 20 | MinStack.prototype.push = function (x) { 21 | var min = this.getMin(); 22 | 23 | this.stack.push(x); 24 | 25 | if (min === undefined || min >= x) { 26 | this.min.push(x); 27 | } 28 | }; 29 | 30 | /** 31 | * @returns {void} 32 | */ 33 | MinStack.prototype.pop = function () { 34 | var val = this.stack.pop(); 35 | var min = this.getMin(); 36 | 37 | if (val === min) { 38 | this.min.pop(); 39 | } 40 | }; 41 | 42 | /** 43 | * @returns {number} 44 | */ 45 | MinStack.prototype.top = function () { 46 | return this.stack[this.stack.length - 1]; 47 | }; 48 | 49 | /** 50 | * @returns {number} 51 | */ 52 | MinStack.prototype.getMin = function () { 53 | return this.min[this.min.length - 1]; 54 | // Caveat: If the first element was the min and it was popped, the array would be empty. 55 | // But the question doesn't mention that scenario, so we are good for now. 56 | }; -------------------------------------------------------------------------------- /138.Copy List with Random Pointer.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list with a random pointer. 3 | * function RandomListNode(label) { 4 | * this.label = label; 5 | * this.next = this.random = null; 6 | * } 7 | */ 8 | 9 | /** 10 | * @param {RandomListNode} head 11 | * @return {RandomListNode} 12 | * 13 | * @TODO: Check for a simpler solution 14 | */ 15 | var copyRandomList = function (head) { 16 | if (!head) return null; 17 | 18 | var result = buildHash(head); 19 | 20 | var p = head, 21 | count = 0, 22 | key; 23 | 24 | 25 | while (p) { 26 | result.list[count].next = result.list[count + 1] === undefined ? null : result.list[count + 1]; 27 | 28 | if (p.random) { 29 | 30 | key = p.random.label + '-' + (p.random.next ? p.random.next.label : 'null') + '-' + (p.random.random ? p.random.random.label : 'null'); 31 | 32 | result.list[count].random = result.list[result.hash[key]]; 33 | 34 | } 35 | 36 | p = p.next; 37 | count++; 38 | } 39 | 40 | return result.list[0]; 41 | }; 42 | 43 | function buildHash(head) { 44 | var hash = {}, 45 | list = [], 46 | prev, 47 | key; 48 | 49 | var p = head, 50 | count = 0; 51 | 52 | while (p) { 53 | key = p.label + '-' + (p.next ? p.next.label : 'null') + '-' + (p.random ? p.random.label : 'null'); 54 | hash[key] = count; 55 | 56 | list[count] = new RandomListNode(p.label); 57 | 58 | count++; 59 | p = p.next; 60 | } 61 | 62 | return { 63 | hash: hash, 64 | list: list 65 | }; 66 | } -------------------------------------------------------------------------------- /161.One Edit Distance.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} s 3 | * @param {string} t 4 | * @return {boolean} 5 | */ 6 | var isOneEditDistance = function (str1, str2) { 7 | var len1 = str1.length; 8 | var len2 = str2.length; 9 | 10 | // CASE 1: If the length difference of the strings is greater than 1 -- return false. 11 | // Also, if both strings are identical -- return false. 12 | if (Math.abs(len1 - len2) > 1 || str1 === str2) { 13 | return false; 14 | } 15 | 16 | // CASE 2: Check for total char differences 17 | var i = 0; 18 | var j = 0; 19 | var diff = 0; 20 | 21 | while (i < len1 && j < len2) { 22 | // If there is a char difference between the 2 strings for the curr index. 23 | if (str1.charAt(i) !== str2.charAt(j)) { 24 | diff++; 25 | if (len1 > len2) { 26 | // Could be that a new character was inserted, so check next char. 27 | i++; 28 | } else if (len2 > len1) { 29 | // Could be that a new character was inserted, so check next char. 30 | j++; 31 | } else { 32 | // If both strings are of same length -- increment both index pointers. 33 | i++; 34 | j++; 35 | } 36 | } else { 37 | // If no difference in characters - move to next char. 38 | i++; 39 | j++; 40 | } 41 | 42 | if (diff > 1) { 43 | // More than one character change - So edit distance > 1 44 | return false; 45 | } 46 | } 47 | 48 | // CASE 3: If the length of the string is not same. ex. "abc" and "abde" are not one edit distance. 49 | if (diff === 1 && len1 !== len2 && (i !== len1 || j !== len2)) { 50 | return false; 51 | } 52 | return true; 53 | }; -------------------------------------------------------------------------------- /078.Subsets.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @return {number[][]} 4 | */ 5 | var subsets = function (nums) { 6 | if (typeof nums === undefined || nums === null) { 7 | return null; 8 | } 9 | 10 | var len = nums.length; 11 | var res = []; 12 | var tempList = []; 13 | nums.sort(function (a, b) { 14 | return a - b; 15 | }); 16 | 17 | for (var i = 0; i <= len; i++) { 18 | helper(nums, tempList, res, i, 0); 19 | } 20 | 21 | return res; 22 | }; 23 | 24 | function helper(nums, tempList, res, targetLen, index) { 25 | if (tempList.length === targetLen) { 26 | res.push(tempList.slice()); 27 | return; 28 | } 29 | 30 | var len = nums.length; 31 | 32 | for (var i = index; i < len; i++) { 33 | tempList.push(nums[i]); 34 | helper(nums, tempList, res, targetLen, i + 1); 35 | tempList.pop(); 36 | } 37 | } 38 | 39 | // Alternative solution 40 | // Returns all combinations 41 | function subsets(nums) { 42 | nums.sort(function (a, b) { 43 | return a - b; 44 | }); 45 | 46 | return combinations(nums); 47 | 48 | function combinations(arr, active, subsets) { 49 | active = active || []; 50 | subsets = subsets || []; 51 | 52 | if (arr.length == 0) { 53 | subsets.push(active); 54 | } else { 55 | combinations(arr.slice(1), active.concat(arr[0]), subsets); 56 | // For string combinations 57 | // combinations(rest.substring(1, rest.length), active + rest.charAt(0)) 58 | 59 | combinations(arr.slice(1), active, subsets); 60 | // For string combinations 61 | // combinations(rest.substring(1, rest.length), active) 62 | } 63 | return subsets; 64 | } 65 | } 66 | 67 | 68 | -------------------------------------------------------------------------------- /023.Merge k Sorted Lists.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[]} lists 10 | * @return {ListNode} 11 | * 12 | * Your runtime beats 92.59% of javascriptsubmissions. 13 | */ 14 | var mergeKLists = function (lists) { 15 | if (!lists || lists.length === 0) { 16 | return null; 17 | } 18 | 19 | var ret = mergeFrom(lists, 0, lists.length - 1); 20 | 21 | return ret; 22 | }; 23 | 24 | function mergeFrom(lists, l, r) { 25 | if (l === r) { 26 | return lists[l]; 27 | } 28 | if (l + 1 === r) { 29 | return merge(lists[l], lists[r]); 30 | } 31 | 32 | var mid = Math.floor((l + r) / 2); 33 | var left = mergeFrom(lists, l, mid); 34 | var right = mergeFrom(lists, mid + 1, r); 35 | 36 | return merge(left, right); 37 | } 38 | 39 | function merge(l, r) { 40 | if (!l && !r) { 41 | return null; 42 | } 43 | if (!l || !r) { 44 | return l || r; 45 | } 46 | 47 | var head, 48 | p, 49 | result; 50 | 51 | while (l || r) { 52 | if (!l) { 53 | result = next(r, false); 54 | } else if (!r) { 55 | result = next(l, true); 56 | } else if (l.val < r.val) { 57 | result = next(l, true); 58 | } else { 59 | result = next(r, false); 60 | } 61 | 62 | if (p) { 63 | p.next = result[0]; 64 | } 65 | p = result[0]; 66 | if (!head) head = result[0]; 67 | 68 | if (result[1]) { 69 | l = l.next; 70 | } else { 71 | r = r.next; 72 | } 73 | } 74 | 75 | return head; 76 | } 77 | 78 | function next(node, isLeft) { 79 | return [new ListNode(node.val), isLeft]; 80 | } -------------------------------------------------------------------------------- /033.Search in Rotated Sorted Array.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @param {number} target 4 | * @return {number} 5 | * 6 | * @Reference: 7 | * http://www.geeksforgeeks.org/search-an-element-in-a-sorted-and-pivoted-array/ 8 | * 9 | * Your runtime beats 92.16% of javascriptsubmissions. 10 | */ 11 | // Hacky solution 12 | var search = function(nums, target) { 13 | var i; 14 | for(i = 0; i < nums.length; i++) { 15 | if(nums[i] === target) { 16 | return i; 17 | } 18 | } 19 | return -1; 20 | }; 21 | 22 | // Expected solution 23 | var search = function (nums, target) { 24 | var i; 25 | var prev = -Infinity; 26 | for (i = 0; i < nums.length; i++) { 27 | if (nums[i] === target) { 28 | return i; 29 | } 30 | 31 | if (nums[i] < prev) { 32 | // Pivot found out. 33 | break; 34 | } 35 | prev = nums[i]; 36 | } 37 | 38 | // Now do binary search on the new sorted array (newArr) 39 | var foundIndex = binarySearch(nums.slice(i), target); 40 | return (foundIndex === -1) ? -1 : i + foundIndex; 41 | }; 42 | 43 | var binarySearch = function (items, value) { 44 | var startIndex = 0, 45 | stopIndex = items.length - 1, 46 | middle = Math.floor((startIndex + stopIndex) / 2); 47 | // Alternative to Math.floor((a + b) / 2); 48 | // Right shift bitwise operator 49 | // middle = ((startIndex + stopIndex) >> 1); 50 | // or 51 | // middle = ~~((startIndex + stopIndex) / 2); 52 | 53 | while (items[middle] != value && startIndex < stopIndex) { 54 | 55 | //adjust search area 56 | if (value < items[middle]) { 57 | stopIndex = middle - 1; 58 | } else if (value > items[middle]) { 59 | startIndex = middle + 1; 60 | } 61 | 62 | //recalculate middle 63 | middle = Math.floor((stopIndex + startIndex) / 2); 64 | } 65 | 66 | //make sure it's the right value 67 | return (items[middle] != value) ? -1 : middle; 68 | }; -------------------------------------------------------------------------------- /140.Word Break II.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} s 3 | * @param {set} wordDict 4 | * Note: wordDict is a Set object, see: 5 | * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set 6 | * @return {string[]} 7 | * 8 | * Your runtime beats 100.00% of javascriptsubmissions. 9 | */ 10 | 11 | var wordBreak = function (str, wordDict, cache) { 12 | if (!str) { 13 | return ['']; 14 | } 15 | 16 | if (str.length === 1 && wordDict.indexOf(str) !== -1) { 17 | return [str]; 18 | } 19 | 20 | if (!wordDict || wordDict.length === 0) { 21 | return ['']; 22 | } 23 | 24 | cache = cache || {}; 25 | if (cache[str] !== undefined) { 26 | return cache[str]; 27 | } 28 | 29 | var solutions = []; 30 | 31 | for (var i = 1; i <= str.length; i++) { 32 | if (wordDict.indexOf(str.slice(0, i)) !== -1) { 33 | // Recursion (Sub problem - Dynamic Programming) 34 | var chunks = wordBreak(str.slice(i), wordDict, cache); 35 | 36 | chunks.forEach(function (chunk) { 37 | // Note: the `chunk` could be a single word or a space separated valid sentence. 38 | solutions.push(str.slice(0, i) + (chunk ? (' ' + chunk) : '')); 39 | }); 40 | } 41 | } 42 | 43 | cache[str] = solutions; 44 | 45 | return solutions; 46 | }; 47 | 48 | console.log(wordBreak("catsanddog", ["cat", "cats", "and", "sand", "dog"])); 49 | // ["cat sand dog", "cats and dog"] 50 | 51 | 52 | // SIMPLER ATTEMPT 53 | 54 | function wordBreak(str, dict, result, finalRes) { 55 | if (!str || !str.length || !dict.length) { 56 | return; 57 | } 58 | 59 | result = result || []; 60 | finalRes = finalRes || []; 61 | 62 | var currStr = ''; 63 | for (var i = 0; i < str.length; i++) { 64 | currStr = str.substr(0, i + 1); 65 | if (dict.indexOf(currStr) !== -1) { 66 | result.push(currStr); 67 | wordBreak(str.slice(i + 1), dict, result); 68 | finalRes.push(result.join(' ')); 69 | result = []; 70 | } 71 | } 72 | 73 | return finalRes; 74 | } 75 | 76 | console.log(wordBreak("catsanddog", ["cat", "cats", "and", "sand", "dog"])); 77 | // ["cat sand dog", "cats and dog"] -------------------------------------------------------------------------------- /291.Word-Pattern-II.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} pattern 3 | * @param {string} str 4 | * @return {boolean} 5 | * 6 | * Your runtime beats 100% of javascript submissions. 7 | * 8 | * @Reference: 9 | * Java version: https://leetcode.com/discuss/63252/share-my-java-backtracking-solution 10 | */ 11 | 12 | var wordPatternMatch = function (pattern, str) { 13 | var patternStrMap = {}; // A map of key-value pairs where key -> pattern letter and value -> corresponding string chunk from str. 14 | var strChunkSet = []; // Set containing unique string chunks which are being matched with the pattern letters 15 | 16 | return isMatch(str, 0, pattern, 0, patternStrMap, strChunkSet); 17 | }; 18 | 19 | var isMatch = function (str, currStrIndex, pattern, currPatternIndex, patternStrMap, strChunkSet) { 20 | // When both the string and the pattern have been checked completely and match 21 | if (currStrIndex === str.length && currPatternIndex === pattern.length) { 22 | return true; 23 | } 24 | 25 | // When one of either str or pattern has been checked completely, but the other isn't. 26 | if (currStrIndex === str.length || currPatternIndex === pattern.length) { 27 | return false; 28 | } 29 | 30 | // Get the current pattern character 31 | var currentPatternChar = pattern[currPatternIndex]; 32 | 33 | // if the pattern character exists in patternStrMap 34 | if (currentPatternChar in patternStrMap) { 35 | var currentMappedStr = patternStrMap[currentPatternChar]; 36 | 37 | // then check if we can use it to match str[currStrIndex... currStrIndex+s.length] 38 | if (str.substr(currStrIndex, currentMappedStr.length) !== currentMappedStr) { 39 | return false; 40 | } 41 | 42 | // If it can match, great, continue to match the rest. 43 | return isMatch(str, currStrIndex + currentMappedStr.length, pattern, currPatternIndex + 1, patternStrMap, strChunkSet); 44 | } else { 45 | // pattern character does not exist in the patternStrMap 46 | for (var i = currStrIndex; i < str.length; i++) { 47 | var strChunk = str.substring(currStrIndex, i + 1); 48 | if (strChunkSet.indexOf(strChunk) !== -1) { 49 | continue; 50 | } 51 | 52 | // Create or update it. 53 | patternStrMap[currentPatternChar] = strChunk; 54 | 55 | if (strChunkSet.indexOf(strChunk) === -1) { 56 | strChunkSet.push(strChunk); 57 | } 58 | // Continue to match the rest 59 | if (isMatch(str, i + 1, pattern, currPatternIndex + 1, patternStrMap, strChunkSet)) { 60 | return true; 61 | } 62 | 63 | // backtracking 64 | if (currentPatternChar in patternStrMap) { 65 | delete patternStrMap[currentPatternChar]; 66 | } 67 | 68 | var strChunkIndex = strChunkSet.indexOf(strChunk); 69 | if (strChunkIndex > -1) { 70 | strChunkSet.splice(strChunkIndex, 1); 71 | } 72 | } 73 | } 74 | // No luck 75 | return false; 76 | }; -------------------------------------------------------------------------------- /208.Implement Trie (Prefix Tree).js: -------------------------------------------------------------------------------- 1 | /** 2 | * @constructor 3 | * Initialize your data structure here. 4 | * 5 | * Your runtime beats 100.00% of javascriptsubmissions. 6 | */ 7 | var TrieNode = function (val) { 8 | this.isLast = false; 9 | this.children = []; 10 | this.val = val; 11 | }; 12 | 13 | var Trie = function () { 14 | this.root = new TrieNode(); 15 | }; 16 | 17 | /** 18 | * @param {string} word 19 | * @return {void} 20 | * Inserts a word into the trie. 21 | */ 22 | Trie.prototype.insert = function (word) { 23 | var i = 0, 24 | j = 0, 25 | l, 26 | temp, 27 | children, 28 | current = this.root; 29 | 30 | var letters = word.split(''); 31 | 32 | for (j = 0; j < letters.length; j++) { 33 | l = letters[j]; 34 | children = current.children; 35 | for (i = 0; i < children.length; i++) { 36 | if (children[i].val === l) { 37 | current = current.children[i]; 38 | break; 39 | } 40 | } 41 | if (i === children.length) { 42 | temp = new TrieNode(l); 43 | children.push(temp); 44 | current = temp; 45 | } 46 | if (j === letters.length - 1) { 47 | current.isLast = true; 48 | } 49 | } 50 | }; 51 | 52 | /** 53 | * @param {string} word 54 | * @return {boolean} 55 | * Returns if the word is in the trie. 56 | */ 57 | Trie.prototype.search = function (word) { 58 | var current = this.root, 59 | i, 60 | j, 61 | l, 62 | children; 63 | 64 | var letters = word.split(''); 65 | 66 | for (j = 0; j < letters.length; j++) { 67 | l = letters[j]; 68 | children = current.children; 69 | for (i = 0; i < children.length; i++) { 70 | if (children[i].val === l) { 71 | current = children[i]; 72 | break; 73 | } 74 | } 75 | if (i === children.length) return false; 76 | } 77 | 78 | if (j === letters.length && current.isLast) return true; 79 | 80 | return false; 81 | }; 82 | 83 | /** 84 | * @param {string} prefix 85 | * @return {boolean} 86 | * Returns if there is any word in the trie 87 | * that starts with the given prefix. 88 | */ 89 | Trie.prototype.startsWith = function (prefix) { 90 | var current = this.root, 91 | i, 92 | j, 93 | l, 94 | children; 95 | 96 | var letters = prefix.split(''); 97 | 98 | for (j = 0; j < letters.length; j++) { 99 | l = letters[j]; 100 | children = current.children; 101 | for (i = 0; i < children.length; i++) { 102 | if (children[i].val === l) { 103 | current = children[i]; 104 | break; 105 | } 106 | } 107 | if (i === children.length) return false; 108 | } 109 | 110 | return true; 111 | }; 112 | 113 | /** 114 | * Your Trie object will be instantiated and called as such: 115 | * var trie = new Trie(); 116 | * trie.insert("somestring"); 117 | * trie.search("key"); 118 | */ --------------------------------------------------------------------------------