diff --git a/11 Container With Most Water.js b/11 Container With Most Water.js index 4afac2b..3e1a596 100644 --- a/11 Container With Most Water.js +++ b/11 Container With Most Water.js @@ -1,3 +1,29 @@ +// 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 line i is at (i, ai) and (i, 0). Find two lines, which together with x-axis forms a container, such that the container contains the most water. +// +// Note: You may not slant the container and n is at least 2. +// +// 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. +// +// Example: +// +// Input: [1,8,6,2,5,4,8,3,7] +// Output: 49 +// + + +// Given fixed set of vertical bars +// Min case +// +// . . +// . . . . +// . . . . . . + +// Max case +// +// . . +// . . . . +// . . . . . . + /** * @param {number[]} height * @return {number} @@ -6,17 +32,17 @@ var maxArea = function(height) { var left = 0; var right = height.length - 1; var maxVal = 0; - + while(left= height[right]){ right--; } else { left++; } } - + return maxVal; -}; \ No newline at end of file +}; diff --git a/15 3Sum.js b/15 3Sum.js index a2f21ec..cecfe00 100644 --- a/15 3Sum.js +++ b/15 3Sum.js @@ -33,8 +33,8 @@ var threeSum = function(nums) { for(var i = 0; i < len-2; i++){ - if(i === 0 || nums[i] > nums[i-1]){ // very important, same as line 40, remove duplicate as 111 will only run once 1-> rather tan 1 1 1 - target = 0 - nums[i]; + if(i === 0 || nums[i] > nums[i-1]){ // very important, same as line 40, remove duplicate as 111 will only run once 1-> rather than 1 1 1 + var target = 0 - nums[i]; j = i + 1; k = len - 1; diff --git a/158 Read N Characters Give Read4 II - Call Multiple Times.js b/158 Read N Characters Give Read4 II - Call Multiple Times.js index 27efed5..2230a88 100644 --- a/158 Read N Characters Give Read4 II - Call Multiple Times.js +++ b/158 Read N Characters Give Read4 II - Call Multiple Times.js @@ -63,3 +63,36 @@ var solution = function(read4) { return numChrRead; }; }; + +var solution = function(read4) { + /** + * @param {character[]} buf Destination buffer + * @param {number} n Number of characters to read + * @return {number} The number of actual characters read + */ + var read4Buff = []; + var read4NumCharRead = 0; + var read4Remain = 0; + + return function(buf, n) { + var numCharRead = 0; + + // Need to run read4 N times to get n char + while(numCharRead < n) { + // If everything is already read in read4 buffer, re-read + if (read4NumCharRead === read4Remain) { + read4NumCharRead = 0; + read4Remain = read4(read4Buff); + } + while(read4NumCharRead < read4Remain && numCharRead < n) { + buf[numCharRead++] = read4Buff[read4NumCharRead++]; + } + if (read4Remain < 4) { + break; + } + + } + + return numCharRead; + }; +}; \ No newline at end of file diff --git a/159 Longest Substring with At Most Two Disctinct Characters.js b/159 Longest Substring with At Most Two Disctinct Characters.js index 2920d0d..aae47ba 100644 --- a/159 Longest Substring with At Most Two Disctinct Characters.js +++ b/159 Longest Substring with At Most Two Disctinct Characters.js @@ -4,6 +4,9 @@ * @param {string} s * @return {number} */ + + // Time O(N) + // Space O(1) var lengthOfLongestSubstringTwoDistinct = function(s) { var longestSubstr = ""; var maxLength = 0; @@ -15,15 +18,14 @@ var lengthOfLongestSubstringTwoDistinct = function(s) { // if map already contains two distrinct chars and the char is new to the map if(map.size > 1 && map.get(c) === undefined) { - var leftMost = s.length; - // Calc substring len before the new char if(i - start > maxLength) { // Should not include i, since i is the new distinct char's index longestSubstr = s.substring(start, i); maxLength = longestSubstr.length; } - + // Find the left most char + var leftMost = s.length; map.forEach((charIdx, key)=> { if(charIdx < leftMost) { leftMost = charIdx; @@ -44,3 +46,42 @@ var lengthOfLongestSubstringTwoDistinct = function(s) { return maxLength; }; + + + + +/** + * @param {string} s + * @return {number} + */ +var lengthOfLongestSubstringTwoDistinct = function(s) { + var map = new Map(); + var start = 0; + var maxLen = 0; + + for(var i = 0; i < s.length; i++) { + var c = s[i]; + if (map.size === 2 && map.get(c) === undefined) { + var curStr; + if (i - start > maxLen) { + maxLen = i - start; + } + var leftMost = s.length; + map.forEach((charIdx, key) => { + if (charIdx < leftMost) { + leftMost = charIdx; + } + }); + start = leftMost + 1; + map.delete(s[leftMost]); + } + + map.set(c, i); + } + + if (s.length - start > maxLen) { + maxLen = s.length - start; + } + + return maxLen; +}; \ No newline at end of file diff --git a/163 Missing Ranges.js b/163 Missing Ranges.js new file mode 100644 index 0000000..ce31cfb --- /dev/null +++ b/163 Missing Ranges.js @@ -0,0 +1,39 @@ +/** + * @param {number[]} nums + * @param {number} lower + * @param {number} upper + * @return {string[]} + */ +var findMissingRanges = function(nums, lower, upper) { + var missing = []; + if (nums.length === 0) { + missing.push(getRange(lower,upper)); + return missing; + } + + // Only need to search range between lower and upper + var next = lower; + for(var i = 0; i < nums.length; i++) { + var val = nums[i]; + + if (val < next) { + continue; + } else if (val === next) { + next++; + continue; + } + // val > next + missing.push(getRange(next, val-1)); + next = val + 1; + } + + if (next <= upper) { + missing.push(getRange(next, upper)); + } + + return missing; +}; + +function getRange(lower, upper) { + return upper === lower ? `${lower}` : `${lower}->${upper}`; +} \ No newline at end of file diff --git a/2 Add Two Numbers.js b/2 Add Two Numbers.js deleted file mode 100644 index b13270e..0000000 --- a/2 Add Two Numbers.js +++ /dev/null @@ -1,73 +0,0 @@ -// You are given two linked lists representing two non-negative numbers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list. - -// Input: (2 -> 4 -> 3) + (5 -> 6 -> 4) -// Output: 7 -> 0 -> 8 - -// Amazon Microsoft Bloomberg Airbnb Adobe - -/** - * Definition for singly-linked list. - * function ListNode(val) { - * this.val = val; - * this.next = null; - * } - */ -/** - * @param {ListNode} l1 - * @param {ListNode} l2 - * @return {ListNode} - */ - - - -// value reverse helps to asslign the first digit or both linklist - -var addTwoNumbers = function(l1, l2) { - if(l1 === null || l2 === null){ - return l1 || l2; - } - - var result = new ListNode(0); - var cur = result; - var p = l1; - var q = l2; - var carry = 0; - - while(p || q){ - var qval; - var pval; - - if(q){ - qval = q.val; - q = q.next; - } else { - qval = 0; - } - - if(p){ - pval = p.val; - p = p.next; - } else { - pval = 0; - } - - var val = qval + pval + carry; - - if(val > 9){ - carry = 1; - val %= 10; - } else { - carry = 0; - } - - cur.next = new ListNode(val); - cur = cur.next; - } - - if(carry !== 0){ - cur.next = new ListNode(1); - } - - return result.next; - -}; \ No newline at end of file diff --git a/31 Next Permutation.js b/31 Next Permutation.js index 214b022..1f90369 100644 --- a/31 Next Permutation.js +++ b/31 Next Permutation.js @@ -6,13 +6,22 @@ var nextPermutation = function(nums) { var vioIndex = nums.length - 1; + + // example + // 1. 687432 + // the violation index is 1 (number 8) since it's greater than index 0 (number 6) + // 2. 87452 + // the violation index is 3 (number 5) since it's greater than index 2 (number 4) while(vioIndex > 0) { if(nums[vioIndex - 1] < nums[vioIndex]) { break; } vioIndex--; } - + + + // If it's not already the maximum value i.e. 876432 in the example of 687432 the maximum is 876432 + // then swap the the 6 with 7 since 7 a just a tad bigger if(vioIndex > 0) { vioIndex--; var first = nums.length - 1; @@ -37,4 +46,49 @@ var nextPermutation = function(nums) { end--; vioIndex++; } +}; + + + +/** + * @param {number[]} nums + * @return {void} Do not return anything, modify nums in-place instead. + */ +var nextPermutation = function(nums) { + var violatedIndex = nums.length - 1; + + while(violatedIndex > 0) { + if (nums[violatedIndex] > nums[violatedIndex-1]) { + break; + } + violatedIndex--; + } + + // max + if (violatedIndex > 0) { + violatedIndex--; + + var indexToSwapWith = nums.length - 1; + while(indexToSwapWith > violatedIndex) { + if (nums[indexToSwapWith] > nums[violatedIndex]) { + var temp = nums[violatedIndex]; + nums[violatedIndex] = nums[indexToSwapWith]; + nums[indexToSwapWith] = temp; + break; + } + indexToSwapWith-- + } + + violatedIndex++; + } + + var end = nums.length - 1; + + while(end > violatedIndex) { + temp = nums[violatedIndex]; + nums[violatedIndex] = nums[end]; + nums[end] = temp; + end-- + violatedIndex++; + } }; \ No newline at end of file diff --git a/4. Median of Two Sorted Arrays.js b/4. Median of Two Sorted Arrays.js deleted file mode 100644 index 0b85a80..0000000 --- a/4. Median of Two Sorted Arrays.js +++ /dev/null @@ -1,94 +0,0 @@ -// /** -// * @param {number[]} nums1 -// * @param {number[]} nums2 -// * @return {number} -// */ - -// // http://blog.csdn.net/yutianzuijin/article/details/11499917 -// var findMedianSortedArrays = function(nums1, nums2) { -// var m = nums1.length; -// var n = nums2.length; -// var total = m + n; - -// if(total%2 === 1) { -// return findKth(nums1, m, nums2, n, parseInt(total/2) + 1); -// } else { -// return (findKth(nums1, m, nums2, n, parseInt(total/2)) + findKth(nums1, m, nums2, n, parseInt(total/2) + 1))/2; -// } -// }; - - -// function findKth(a, m, b, n, k) { -// // always assume that m is equal or smaller than n -// if(m > n) { -// return findKth(b, n, a, m, k); -// } - -// if(m === 0) { -// return b[k-1]; -// } - -// if(k === 1) { -// return Math.min(a[0],b[0]); -// } - -// // divide k into two parts -// var pa = Math.min(parseInt(k/2), m); -// var pb = k - pa; - -// if(a[pa - 1] < b[pb - 1]) { -// return findKth(a.slice(pa), m - pa, b, n, k - pa); -// } else if(a[pa - 1] > b[pb - 1]) { -// return findKth(a, m, b.slice(pb), n - pb, k - pb); -// } else { -// return a[pa - 1]; -// } -// } - - -/** - * @param {number[]} nums1 - * @param {number[]} nums2 - * @return {number} - */ -var findMedianSortedArrays = function(nums1, nums2) { - var total = nums1.length + nums2.length; - - if (total % 2 === 1) { - return findKth(nums1, 0, nums2, 0, parseInt(total/2) + 1); - } else { - return ( - findKth(nums1, 0, nums2, 0, parseInt(total/2)) - + findKth(nums1, 0, nums2, 0, parseInt(total/2) + 1) - )/2; - } -}; - -function findKth(nums1, start1, nums2, start2, kth) { - var len1 = nums1.length - start1; - var len2 = nums2.length - start2; - - if (len1 > len2) { - return findKth(nums2, start2, nums1, start1, kth); - } - - if (len1 === 0) { - return nums2[kth - 1]; - } - - if (kth === 1) { - return Math.min(nums1[start1], nums2[start2]); - } - - // divide kth into 2 parts - var part1 = Math.min(parseInt(kth/2), len1); - var part2 = kth - part1; - - if (nums1[start1 + part1 - 1] < nums2[start2 + part2 - 1]) { - return findKth(nums1, start1 + part1, nums2, start2, kth - part1); - } else if (nums1[start1 + part1 - 1] > nums2[start2 + part2 - 1]) { - return findKth(nums1, start1, nums2, start2 + part2, kth - part2); - } else { - return nums1[start1 + part1 - 1]; - } -} \ No newline at end of file diff --git a/48 Rotate Image.js b/48 Rotate Image.js index 546ab53..46a0072 100644 --- a/48 Rotate Image.js +++ b/48 Rotate Image.js @@ -71,3 +71,42 @@ var swap = function(matrix, i1, j1, i2, j2) { matrix[i2][j2] = aux; }; + + + +/** + * @param {number[][]} matrix + * @return {void} Do not return anything, modify matrix in-place instead. + */ +var rotate = function(matrix) { + rotateDiagonal(matrix); + rotateRow(matrix); +}; + +var swap = function(matrix, x1, y1, x2, y2) { + var temp = matrix[x1][y1]; + matrix[x1][y1] = matrix[x2][y2]; + matrix[x2][y2] = temp; +} + +var rotateRow = function(matrix) { + for(var i = 0; i < matrix.length; i++) { + var row = matrix[i]; + var start = 0; + var end = matrix[i].length - 1; + + while(start < end) { + swap(matrix, i, start, i, end); + start++; + end--; + } + } +} + +var rotateDiagonal = function(matrix) { + for(var i = 0; i < matrix.length; i++) { + for(var j = i; j < matrix.length; j++) { + swap(matrix, i, j, j, i); + } + } +} \ No newline at end of file diff --git a/55 Jump Game.js b/55 Jump Game.js index a31f2f4..1433dc6 100644 --- a/55 Jump Game.js +++ b/55 Jump Game.js @@ -11,6 +11,5 @@ var canJump = function(nums) { } numLeft = Math.max(nums[i], numLeft); } - - return numLeft >= 0; + return true; }; \ No newline at end of file diff --git a/66 Plus One.js b/66 Plus One.js index 0d1c6cb..9dae196 100644 --- a/66 Plus One.js +++ b/66 Plus One.js @@ -2,6 +2,35 @@ * @param {number[]} digits * @return {number[]} */ + +// Time complexity : \mathcal{O}(N)O(N) since it's not more than one pass along the input list. + +// Space complexity : \mathcal{O}(1)O(1). +var plusOne = function(digits) { + var carry = 1; + for(var i = digits.length - 1; i > -1; i--) { + var d = digits[i]; + var sum = d + carry; + if (sum === 10) { + digits[i] = 0; + carry = 1; + } else { + digits[i] = sum; + carry = 0; // can directly return since it will not trigger the carry unshift at the end. + break; + } + } + + if (carry === 1) { + digits.unshift(carry); + } + + return digits; +}; + + + + var plusOne = function(digits) { for(var i = digits.length; i--;){ digits[i] = 1 + digits[i]; diff --git a/681 Next Closest Time .js b/681 Next Closest Time .js new file mode 100644 index 0000000..41a2ef9 --- /dev/null +++ b/681 Next Closest Time .js @@ -0,0 +1,75 @@ +// Given a time represented in the format "HH:MM", form the next closest time by reusing the current digits. There is no limit on how many times a digit can be reused. + +// You may assume the given input string is always valid. For example, "01:34", "12:09" are all valid. "1:34", "12:9" are all invalid. + +// Example 1: + +// Input: "19:34" +// Output: "19:39" +// Explanation: The next closest time choosing from digits 1, 9, 3, 4, is 19:39, which occurs 5 minutes later. It is not 19:33, because this occurs 23 hours and 59 minutes later. +// Example 2: + +// Input: "23:59" +// Output: "22:22" +// Explanation: The next closest time choosing from digits 2, 3, 5, 9, is 22:22. It may be assumed that the returned time is next day's time since it is smaller than the input time numerically. + + + + +// Approach #1: Simulation [Accepted] +// Intuition and Algorithm + +// Simulate the clock going forward by one minute. Each time it moves forward, if all the digits are allowed, then return the current time. + +// The natural way to represent the time is as an integer t in the range 0 <= t < 24 * 60. Then the hours are t / 60, the minutes are t % 60, and each digit of the hours and minutes can be found by hours / 10, hours % 10 etc. + +/** + * @param {string} time + * @return {string} + */ +var nextClosestTime = function(time) { + let cur = 60 * parseInt(time.substring(0, 2)); + cur += parseInt(time.substring(3)); + const allowed = new Set(); + + for(var i = 0; i < time.length; i++) { + if (time[i] !== ':') { + allowed.add(parseInt(time[i])); + } + } + + while(true) { + cur = (cur + 1) % (24*60); + var curTime = [ + Math.floor(cur / 60 / 10), // hour 24 -> 2 + Math.floor(cur / 60) % 10, // hour 24 -> 4 + Math.floor((cur % 60) / 10), // minutes 59 -> 5 + cur % 60 % 10, // minutes 59 -> 9 + ]; + + for(i = 0; i < curTime.length; i++) { + var t = curTime[i]; + if (!allowed.has(t)) { + break; + } + if (i === curTime.length - 1) { + let hour = Math.floor(cur / 60); + let min = cur % 60; + + if (hour < 10) { + hour = '0' + hour; + } else { + hour = '' + hour; + } + + if (min < 10) { + min = '0' + min; + } else { + min = '' + min; + } + + return hour + ':' + min; + } + } + } +}; \ No newline at end of file diff --git a/76 Minimum Window Substring.js b/76 Minimum Window Substring.js index c5e1262..e18e98b 100644 --- a/76 Minimum Window Substring.js +++ b/76 Minimum Window Substring.js @@ -26,8 +26,8 @@ var minWindow = function(s, t) { var lenS = s.length; var lenT = t.length; var queue = []; - var tRequireCount = {}; - var tFoundCount = {}; + var tRequireCount = {}; // string T required count + var tFoundCount = {}; // string T found count var hasFound = 0; var windowBeg = -1; var windowEnd = lenS; @@ -41,6 +41,7 @@ var minWindow = function(s, t) { } for(i = 0; i < lenS; i++) { + // cannot use tRequireCount[s[i]] !== 0 since tRequireCount[s[i]] might be undefined if(tRequireCount[s[i]] > 0) { // use queue to skip a lot of redudant character // minWindow('aeeeeeebceeeeaeeedcb', 'abc'); @@ -53,7 +54,13 @@ var minWindow = function(s, t) { // if found count is over require count, we don't need those extra, so don't record it to hasFound if(tFoundCount[s[i]] <= tRequireCount[s[i]]) { - hasFound++; + // hasFound is used as a flag for knowing where we should check against T string and when we should start reducing the range + // for example + // minWindow('aaaaebceeeeaeeedcb', 'abc'); + // at index 5 where s[i] is e, hasFound is 1 and tFoundCount['a'] is 4, queue=[0,1,2,3] + // when we arrive at index 7 where s[i] is c, has found is now 3 and is equal to lenT + // now we can start reducing the range all the way from index 0(a) to index 7(c) to index 3(a) to index 7 (c) which will give us the min + hasFound++; } // when the current location which is in queue @@ -73,9 +80,67 @@ var minWindow = function(s, t) { // 1st round 0 8 // 2nd round 7 13 } + // since i must be the last match that leads to hasFound === lenT + hasFound--; + } + } + } + + return windowBeg !== -1 ? s.substring(windowBeg, windowEnd + 1) : ''; +}; + + +/** + * @param {string} s + * @param {string} t + * @return {string} + */ +var minWindow = function(s, t) { + var lenS = s.length; + var lenT = t.length; + var tCharToFoundCount = {}; + var tCharToRequiredCount = {}; + + for(var i = 0; i < lenT; i++) { + var c = t[i]; + tCharToFoundCount[c] = 0; + tCharToRequiredCount[c] = tCharToRequiredCount[c] || 0; + tCharToRequiredCount[c]++; + } + + var windowBeg = -1; + var windowEnd = lenS; + var queue = []; + var hasFound = 0; + for(i = 0; i < lenS; i++) { + c = s[i]; + // skip unneeded char + if (tCharToRequiredCount[c] !== 0) { + tCharToFoundCount[c]++; + queue.push(i); + + if (tCharToFoundCount[c] <= tCharToRequiredCount[c]) { + hasFound++; + } + + if (hasFound === lenT) { + var k; + + do { + k = queue.shift(); + tCharToFoundCount[s[k]]--; + } while(tCharToFoundCount[s[k]] >= tCharToRequiredCount[s[k]]); + + if (windowEnd - windowBeg > i - k) { + windowBeg = k; + windowEnd = i; + } + hasFound--; } + + } } diff --git a/1 Two Sum.js b/[0001] Two Sum.js similarity index 100% rename from 1 Two Sum.js rename to [0001] Two Sum.js diff --git a/[0002] Add Two Numbers.js b/[0002] Add Two Numbers.js new file mode 100644 index 0000000..8142f50 --- /dev/null +++ b/[0002] Add Two Numbers.js @@ -0,0 +1,55 @@ +// You are given two linked lists representing two non-negative numbers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list. + +// Input: (2 -> 4 -> 3) + (5 -> 6 -> 4) +// Output: 7 -> 0 -> 8 + +// Amazon Microsoft Bloomberg Airbnb Adobe + +/** + * Definition for singly-linked list. + * function ListNode(val) { + * this.val = val; + * this.next = null; + * } + */ +/** + * @param {ListNode} l1 + * @param {ListNode} l2 + * @return {ListNode} + */ + + + +// value reverse helps to asslign the first digit or both linklist +var addTwoNumbers = function(l1, l2) { + const answer = new ListNode(0); + var node = answer; + var carry = 0; + while(l1 !== null || l2 !== null || carry !== 0) { + var val = 0; + if (carry !== 0) { + val += carry; + } + carry = 0; + if (l1 !== null) { + val += l1.val; + } + if (l2 !== null) { + val += l2.val; + } + if (val > 9) { + val -= 10; + carry = 1; + } + node.next = new ListNode(val); + node = node.next; + if (l1 !== null) { + l1 = l1.next; + } + if (l2 !== null) { + l2 = l2.next; + } + } + + return answer.next; +}; diff --git a/3 Longest Substring Without Repeating Characters.js b/[0003] Longest Substring Without Repeating Characters.js similarity index 86% rename from 3 Longest Substring Without Repeating Characters.js rename to [0003] Longest Substring Without Repeating Characters.js index 41f4575..d917b15 100644 --- a/3 Longest Substring Without Repeating Characters.js +++ b/[0003] Longest Substring Without Repeating Characters.js @@ -4,6 +4,9 @@ */ +// use map for storing index +// if a repeated character is found, skip directly to the index of the repeated character in the map. + var lengthOfLongestSubstring = function(s) { if(s === null || s.length === 0){ return 0; diff --git a/[0004] Median of Two Sorted Arrays.js b/[0004] Median of Two Sorted Arrays.js new file mode 100644 index 0000000..33e7fb2 --- /dev/null +++ b/[0004] Median of Two Sorted Arrays.js @@ -0,0 +1,146 @@ +// /** +// * @param {number[]} nums1 +// * @param {number[]} nums2 +// * @return {number} +// */ + +// // http://blog.csdn.net/yutianzuijin/article/details/11499917 +// var findMedianSortedArrays = function(nums1, nums2) { +// var m = nums1.length; +// var n = nums2.length; +// var total = m + n; + +// if(total%2 === 1) { +// return findKth(nums1, m, nums2, n, parseInt(total/2) + 1); +// } else { +// return (findKth(nums1, m, nums2, n, parseInt(total/2)) + findKth(nums1, m, nums2, n, parseInt(total/2) + 1))/2; +// } +// }; + + +// function findKth(a, m, b, n, k) { +// // always assume that m is equal or smaller than n +// if(m > n) { +// return findKth(b, n, a, m, k); +// } + +// if(m === 0) { +// return b[k-1]; +// } + +// if(k === 1) { +// return Math.min(a[0],b[0]); +// } + +// // divide k into two parts +// var pa = Math.min(parseInt(k/2), m); +// var pb = k - pa; + +// if(a[pa - 1] < b[pb - 1]) { +// return findKth(a.slice(pa), m - pa, b, n, k - pa); +// } else if(a[pa - 1] > b[pb - 1]) { +// return findKth(a, m, b.slice(pb), n - pb, k - pb); +// } else { +// return a[pa - 1]; +// } +// } + + +// /** +// * @param {number[]} nums1 +// * @param {number[]} nums2 +// * @return {number} +// */ +// var findMedianSortedArrays = function(nums1, nums2) { +// var total = nums1.length + nums2.length; +// +// if (total % 2 === 1) { +// return findKth(nums1, 0, nums2, 0, parseInt(total/2) + 1); +// } else { +// return ( +// findKth(nums1, 0, nums2, 0, parseInt(total/2)) +// + findKth(nums1, 0, nums2, 0, parseInt(total/2) + 1) +// )/2; +// } +// }; +// +// function findKth(nums1, start1, nums2, start2, kth) { +// var len1 = nums1.length - start1; +// var len2 = nums2.length - start2; +// +// if (len1 > len2) { +// return findKth(nums2, start2, nums1, start1, kth); +// } +// +// if (len1 === 0) { +// return nums2[kth - 1]; +// } +// +// if (kth === 1) { +// return Math.min(nums1[start1], nums2[start2]); +// } +// +// // divide kth into 2 parts +// var part1 = Math.min(parseInt(kth/2), len1); +// var part2 = kth - part1; +// +// if (nums1[start1 + part1 - 1] < nums2[start2 + part2 - 1]) { +// return findKth(nums1, start1 + part1, nums2, start2, kth - part1); +// } else if (nums1[start1 + part1 - 1] > nums2[start2 + part2 - 1]) { +// return findKth(nums1, start1, nums2, start2 + part2, kth - part2); +// } else { +// return nums1[start1 + part1 - 1]; +// } +// } + + + +/** + * @param {number[]} nums1 + * @param {number[]} nums2 + * @return {number} + */ +var findMedianSortedArrays = function(nums1, nums2) { + const len = nums1.length + nums2.length; + + if (len % 2 === 1) { + return findKth(nums1, 0, nums2, 0, Math.floor(len/2) + 1); + } else { + const first = findKth(nums1, 0, nums2, 0, Math.floor(len/2)); + const second = findKth(nums1, 0, nums2, 0, Math.floor(len/2) + 1); + + return (first + second) / 2; + } +}; + +function findKth(nums1, start1, nums2, start2, kth) { + const len1 = nums1.length - start1; + const len2 = nums2.length - start2; + + if (len1 > len2) { + return findKth(nums2, start2, nums1, start1, kth); + } + + if (len1 === 0) { + return nums2[kth - 1]; + } + + if (kth === 1) { + return Math.min(nums1[start1], nums2[start2]); + } + + // Three conditions here, len1 < kth/2, len1 === kth/2, len1 > kth/2 + const kth1 = Math.min(Math.floor(kth/2), len1); + const kth2 = kth - kth1; + + const nums1Kth = nums1[start1 + kth1 - 1]; + const nums2Kth = nums2[start2 + kth2 - 1]; + + if (nums1Kth < nums2Kth) { + return findKth(nums1, start1 + kth1, nums2, start2, kth2); + } else if (nums1Kth > nums2Kth) { + return findKth(nums1, start1, nums2, start2 + kth2, kth1); + } else { + return nums1Kth; + } +} diff --git a/[0004] Median of Two Sorted Arrays.sublime-workspace b/[0004] Median of Two Sorted Arrays.sublime-workspace new file mode 100644 index 0000000..4942cb0 --- /dev/null +++ b/[0004] Median of Two Sorted Arrays.sublime-workspace @@ -0,0 +1,239 @@ +{ + "auto_complete": + { + "selected_items": + [ + [ + "atta", + "attachEvent" + ] + ] + }, + "buffers": + [ + ], + "build_system": "", + "build_system_choices": + [ + ], + "build_varint": "", + "command_palette": + { + "height": 87.0, + "last_filter": "", + "selected_items": + [ + [ + "package install", + "Package Control: Install Package" + ], + [ + "package install ", + "Package Control: Install Package" + ], + [ + "package insta", + "Package Control: Install Package" + ], + [ + "package", + "Install Package Control" + ] + ], + "width": 485.0 + }, + "console": + { + "height": 0.0, + "history": + [ + ] + }, + "distraction_free": + { + "menu_visible": true, + "show_minimap": false, + "show_open_files": false, + "show_tabs": false, + "side_bar_visible": false, + "status_bar_visible": false + }, + "file_history": + [ + "/Users/cyu0/workspace/perkmon/src/routes/home/Home.js", + "/Users/cyu0/workspace/perkmon/src/routes/home/Home.css", + "/Users/cyu0/Downloads/immutable-js-diff-master/tests/sequenceDiff.test.js", + "/Users/cyu0/workspace/perkmon/src/components/Input/Input.css", + "/Users/cyu0/workspace/perkmon/src/components/Html.js", + "/Users/cyu0/workspace/perkmon/src/components/Input/Input.js", + "/Users/cyu0/workspace/perkmon/src/components/SearchWithBgImage/SearchWithBgImage.css", + "/Users/cyu0/workspace/perkmon/src/components/App.js", + "/Users/cyu0/workspace/perkmon/src/lib/event.js", + "/Users/cyu0/workspace/perkmon/src/lib/Event.js", + "/Users/cyu0/workspace/perkmon/src/components/CtaImageWithSearch/SearchWithBgImage.js", + "/Users/cyu0/workspace/perkmon/src/components/CtaImageWithSearch/SearchWithBgImage.css", + "/Users/cyu0/workspace/perkmon/src/components/Header/Header.css", + "/Users/cyu0/workspace/perkmon/src/routes/home/index.js", + "/Users/cyu0/workspace/perkmon/src/components/Header/Header.js", + "/Users/cyu0/workspace/perkmon/src/routes/index.js", + "/Users/cyu0/workspace/perkmon/build/server.js", + "/Users/cyu0/workspace/perkmon/src/", + "/Users/cyu0/workspace/perkmon/src/components/Navigation/Navigation.js", + "/Users/cyu0/workspace/perkmon/node_modules/enzyme/src/ReactWrapper.jsx", + "/Users/cyu0/workspace/perkmon/node_modules/resolve/test/precedence/aaa.js", + "/Users/cyu0/workspace/perkmon/src/components/variables.css", + "/Users/cyu0/workspace/perkmon/package.json" + ], + "find": + { + "height": 24.0 + }, + "find_in_files": + { + "height": 93.0, + "where_history": + [ + ] + }, + "find_state": + { + "case_sensitive": false, + "find_history": + [ + ], + "highlight": true, + "in_selection": false, + "preserve_case": false, + "regex": false, + "replace_history": + [ + ], + "reverse": false, + "show_context": true, + "use_buffer2": true, + "whole_word": false, + "wrap": true + }, + "groups": + [ + { + "sheets": + [ + ] + } + ], + "incremental_find": + { + "height": 24.0 + }, + "input": + { + "height": 31.0 + }, + "layout": + { + "cells": + [ + [ + 0, + 0, + 1, + 1 + ] + ], + "cols": + [ + 0.0, + 1.0 + ], + "rows": + [ + 0.0, + 1.0 + ] + }, + "menu_visible": true, + "output.SublimeLinter": + { + "height": 0.0 + }, + "output.SublimeLinter Messages": + { + "height": 108.0 + }, + "output.find_results": + { + "height": 0.0 + }, + "pinned_build_system": "", + "project": "[0004] Median of Two Sorted Arrays.sublime-project", + "replace": + { + "height": 44.0 + }, + "save_all_on_build": true, + "select_file": + { + "height": 0.0, + "last_filter": "", + "selected_items": + [ + [ + "header.css", + "src/components/Header/Header.css" + ], + [ + "navigation", + "src/components/Navigation/Navigation.js" + ], + [ + "variables.css", + "src/components/variables.css" + ], + [ + "aa.js", + "node_modules/resolve/test/precedence/aaa.js" + ], + [ + ".jsx", + "node_modules/enzyme/src/ReactWrapper.jsx" + ], + [ + ".json", + "package.json" + ] + ], + "width": 0.0 + }, + "select_project": + { + "height": 0.0, + "last_filter": "", + "selected_items": + [ + ], + "width": 0.0 + }, + "select_symbol": + { + "height": 0.0, + "last_filter": "", + "selected_items": + [ + ], + "width": 0.0 + }, + "selected_group": 0, + "settings": + { + }, + "show_minimap": true, + "show_open_files": false, + "show_tabs": true, + "side_bar_visible": true, + "side_bar_width": 300.0, + "status_bar_visible": true, + "template_settings": + { + } +} diff --git a/10 Regular Expresion Matching.js b/[0010] Regular Expresion Matching.js similarity index 100% rename from 10 Regular Expresion Matching.js rename to [0010] Regular Expresion Matching.js diff --git a/key concepts b/key concepts new file mode 100644 index 0000000..b8f94bd --- /dev/null +++ b/key concepts @@ -0,0 +1,3 @@ +1. Substring vs subsequnce: substrings are consecutive subsequences +2. substring without repeating character: use map for storing index and use time window +