From 77db876455ffbea67d5321a5dc33e8cbc29e8520 Mon Sep 17 00:00:00 2001 From: chihungyu1116 Date: Tue, 2 Jan 2018 23:12:11 -0800 Subject: [PATCH 01/10] improved num 4 --- 4. Median of Two Sorted Arrays.js | 98 +++++++++++++++++++++++-------- 1 file changed, 73 insertions(+), 25 deletions(-) diff --git a/4. Median of Two Sorted Arrays.js b/4. Median of Two Sorted Arrays.js index c740e91..0b85a80 100644 --- a/4. Median of Two Sorted Arrays.js +++ b/4. Median of Two Sorted Arrays.js @@ -1,46 +1,94 @@ +// /** +// * @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} */ - -// 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; + var total = nums1.length + nums2.length; - if(total%2 === 1) { - return findKth(nums1, m, nums2, n, parseInt(total/2) + 1); + if (total % 2 === 1) { + return findKth(nums1, 0, nums2, 0, parseInt(total/2) + 1); } else { - return (findKth(nums1, m, nums2, n, parseInt(total/2)) + findKth(nums1, m, nums2, n, parseInt(total/2) + 1))/2; + return ( + findKth(nums1, 0, nums2, 0, parseInt(total/2)) + + findKth(nums1, 0, nums2, 0, 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); +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(m === 0) { - return b[k-1]; + if (len1 === 0) { + return nums2[kth - 1]; } - if(k === 1) { - return Math.min(a[0],b[0]); + if (kth === 1) { + return Math.min(nums1[start1], nums2[start2]); } - // divide k into two parts - var pa = Math.min(parseInt(k/2), m); - var pb = k - pa; + // divide kth into 2 parts + var part1 = Math.min(parseInt(kth/2), len1); + var part2 = kth - part1; - 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); + 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 a[pa - 1]; + return nums1[start1 + part1 - 1]; } } \ No newline at end of file From 4151859e2403cd3893d57d110219db72186a7e2b Mon Sep 17 00:00:00 2001 From: chihungyu1116 Date: Mon, 15 Jan 2018 17:23:32 -0800 Subject: [PATCH 02/10] add more --- 112 Path Sum.js | 27 ++++++++++ 141 Linked List Cycle.js | 63 ++++++++++++++++++----- 190 Reverse Bits.js | 10 ++-- 242 Valid Anagram.js | 39 ++++++++++++++ 26 Remove Duplicates from Sorted Array.js | 23 ++++++++- 278 First Bad Version.js | 49 ++++++++++++++++-- 35 Search Insert Position.js | 51 ++++++++++++++---- 9 Palindrome Number.js | 46 ----------------- 8 files changed, 230 insertions(+), 78 deletions(-) delete mode 100644 9 Palindrome Number.js diff --git a/112 Path Sum.js b/112 Path Sum.js index b9e0d9e..3ecd17f 100644 --- a/112 Path Sum.js +++ b/112 Path Sum.js @@ -24,4 +24,31 @@ var hasPathSum = function(root, sum) { } return hasPathSum(root.left, sum - root.val) || hasPathSum(root.right, sum - root.val); +}; + +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @param {number} sum + * @return {boolean} + */ +var hasPathSum = function(root, sum) { + if (root === null) { + return false; + } + + var left = root.left; + var right = root.right; + + if (left === null && right === null) { + return root.val === sum; + } + + return hasPathSum(left, sum - root.val) || hasPathSum(right, sum - root.val); }; \ No newline at end of file diff --git a/141 Linked List Cycle.js b/141 Linked List Cycle.js index a4d76ad..ea7e272 100644 --- a/141 Linked List Cycle.js +++ b/141 Linked List Cycle.js @@ -2,6 +2,44 @@ // Language: Javascript // Problem: https://leetcode.com/problems/linked-list-cycle/ // Author: Chihung Yu +/** + * Definition for singly-linked list. + * function ListNode(val) { + * this.val = val; + * this.next = null; + * } + */ + +/** + * @param {ListNode} head + * @return {boolean} + */ +// var hasCycle = function(head) { +// if(head === null || head.next === null){ +// return false; +// } + +// var faster = head.next; +// var slower = head; + +// while(faster && slower){ +// if(faster.val === slower.val){ +// return true; +// } +// faster = faster.next; + +// if(faster === null){ +// return false; +// } else { +// faster = faster.next; +// } + +// slower = slower.next; +// } + +// return false; +// }; + /** * Definition for singly-linked list. * function ListNode(val) { @@ -15,26 +53,27 @@ * @return {boolean} */ var hasCycle = function(head) { - if(head === null || head.next === null){ + if (head === null) { return false; } + + var node1 = head; + var node2 = head; + node2 = node2.next; - var faster = head.next; - var slower = head; - - while(faster && slower){ - if(faster.val === slower.val){ + while(node1 !== null && node2 !== null) { + if (node1.val === node2.val) { return true; } - faster = faster.next; + + node1 = node1.next; + node2 = node2.next; - if(faster === null){ - return false; - } else { - faster = faster.next; + if (node2 !== null) { + node2 = node2.next; } - slower = slower.next; + } return false; diff --git a/190 Reverse Bits.js b/190 Reverse Bits.js index 76911a0..04d3eb1 100644 --- a/190 Reverse Bits.js +++ b/190 Reverse Bits.js @@ -9,11 +9,15 @@ var reverseBits = function(n) { var result = 0; - for(var i = 0; i < 32; i++){ + for(var i = 0; i < 31; i++){ result <<= 1; result |= n & 1; - n >>= 1; + + n >>>= 1; + console.log(result, n); } return Math.abs(result); -}; \ No newline at end of file +}; + +console.log(reverseBits(4294967295)); \ No newline at end of file diff --git a/242 Valid Anagram.js b/242 Valid Anagram.js index bccbafb..151c4c0 100644 --- a/242 Valid Anagram.js +++ b/242 Valid Anagram.js @@ -38,4 +38,43 @@ var isAnagram = function(s, t) { } return true; +}; + + + + +/** + * @param {string} s + * @param {string} t + * @return {boolean} + */ +var isAnagram = function(s, t) { + if (s === null || t === null || s.length !== t.length) { + return false; + } + + var hash = {}; + var i; + for(i = 0; i < s.length; i++) { + var sval = s[i]; + var tval = t[i]; + + if (hash[sval] === undefined) { + hash[sval] = 0; + } + + if (hash[tval] === undefined) { + hash[tval] = 0; + } + hash[sval]++; + hash[tval]--; + } + + for(var j in hash) { + if (hash[j] !== 0) { + return false; + } + } + + return true; }; \ No newline at end of file diff --git a/26 Remove Duplicates from Sorted Array.js b/26 Remove Duplicates from Sorted Array.js index 80f8f6a..04f251e 100644 --- a/26 Remove Duplicates from Sorted Array.js +++ b/26 Remove Duplicates from Sorted Array.js @@ -58,4 +58,25 @@ var removeDuplicates = function(nums) { }; -// [tricky] \ No newline at end of file +// [tricky] + +/** + * @param {number[]} nums + * @return {number} + */ +var removeDuplicates = function(nums) { + var hash = {}; + var cur = 0; + + for(var i = 0; i < nums.length; i++) { + var num = nums[i]; + + if (hash[num] === undefined) { + hash[num] = true; + nums[cur] = num; + cur++; + } + } + + return cur; +}; \ No newline at end of file diff --git a/278 First Bad Version.js b/278 First Bad Version.js index 7013caa..bdccb14 100644 --- a/278 First Bad Version.js +++ b/278 First Bad Version.js @@ -14,7 +14,7 @@ /** * Definition for isBadVersion() - * + * * @param {integer} version number * @return {boolean} whether the version is bad * isBadVersion = function(version) { @@ -35,7 +35,7 @@ var solution = function(isBadVersion) { var beg = 0; var end = n; var lastBad; - + while(beg <= end) { var mid = beg + Math.floor((end - beg)/2); if(isBadVersion(mid)) { @@ -43,10 +43,49 @@ var solution = function(isBadVersion) { lastBad = mid; end = mid - 1; } else { - beg = mid + 1; + beg = mid + 1; } } - + return lastBad; }; -}; \ No newline at end of file +}; + + + +/** + * Definition for isBadVersion() + * + * @param {integer} version number + * @return {boolean} whether the version is bad + * isBadVersion = function(version) { + * ... + * }; + */ + +/** + * @param {function} isBadVersion() + * @return {function} + */ +var solution = function(isBadVersion) { + /** + * @param {integer} n Total versions + * @return {integer} The first bad version + */ + return function(n) { + var left = 1; + var right = n; + + while (left < right) { + var mid = left + Math.floor((right - left)/2); + + if (isBadVersion(mid)) { + right = mid; + } else { + left = mid + 1; + } + } + + return left; + }; +}; diff --git a/35 Search Insert Position.js b/35 Search Insert Position.js index 40cc05c..bba8074 100644 --- a/35 Search Insert Position.js +++ b/35 Search Insert Position.js @@ -2,6 +2,37 @@ // Language: Javascript // Problem: https://leetcode.com/problems/search-insert-position/ // Author: Chihung Yu +/** + * @param {number[]} nums + * @param {number} target + * @return {number} + */ +// var searchInsert = function(nums, target) { +// var left = 0; +// var right = nums.length - 1; +// +// while(left <= right){ +// var mid = parseInt((left + right)/2); +// +// var val = nums[mid]; +// +// if(val === target){ +// return mid; +// } else if(val > target){ +// right = mid - 1; +// } else { +// left = mid + 1; +// } +// } +// +// if(nums[left] < target){ +// return left + 1; +// } else { +// return left; +// } +// }; + + /** * @param {number[]} nums * @param {number} target @@ -10,24 +41,22 @@ var searchInsert = function(nums, target) { var left = 0; var right = nums.length - 1; - - while(left <= right){ - var mid = parseInt((left + right)/2); - - var val = nums[mid]; - - if(val === target){ + + while (left < right) { + var mid = left + Math.ceil((right - left)/2); + + if (nums[mid] === target) { return mid; - } else if(val > target){ + } else if (nums[mid] > target) { right = mid - 1; } else { left = mid + 1; } } - - if(nums[left] < target){ + + if (nums[left] < target) { return left + 1; } else { return left; } -}; \ No newline at end of file +} diff --git a/9 Palindrome Number.js b/9 Palindrome Number.js deleted file mode 100644 index 2fc423b..0000000 --- a/9 Palindrome Number.js +++ /dev/null @@ -1,46 +0,0 @@ -// Leetcode #9: -// Language: Javascript -// Problem: https://leetcode.com/problems/palindrome-number/ -// Author: Chihung Yu - -// Determine whether an integer is a palindrome. Do this without extra space. - - /** - * @param {number} x - * @return {boolean} - */ -var isPalindrome = function(x) { - if(x < 0) { - return false; - } - - var div = 1; - - // it means that the div is still a valid divider - // e.g 600 the divider should be 100 at maximum - // e.g. 90 the divider should be 10 at maximum - // e.g. 1 the divider should be a 1 at maximum - while(parseInt(x/div) >= 10) { - div *= 10; - } - - var left, right; - - // when div === 1 it means the digit only has one value to examine - // e.g. 121 -> only 2 is left for examine which can be ignore - // e.g. 1 -> 1 - // e.g. 43234 -> 2 - while(div > 1) { - left = parseInt(x/div); - right = x%10; - if(left !== right) { - return false; - } - - x = x%div; // remove the left most digit - x = parseInt(x/10); // remove the right most digit - div /= 100; - } - - return true; -}; \ No newline at end of file From e40613996c62271facf00778c4802f8ae0878903 Mon Sep 17 00:00:00 2001 From: Chihung Yu Date: Sat, 22 Jun 2019 12:29:03 -0700 Subject: [PATCH 03/10] update --- 1 Two Sum.js | 37 ---------------- 10 Regular Expresion Matching.js | 73 -------------------------------- 2 Add Two Numbers.js | 73 -------------------------------- 3 files changed, 183 deletions(-) delete mode 100644 1 Two Sum.js delete mode 100644 10 Regular Expresion Matching.js delete mode 100644 2 Add Two Numbers.js diff --git a/1 Two Sum.js b/1 Two Sum.js deleted file mode 100644 index ed67bd0..0000000 --- a/1 Two Sum.js +++ /dev/null @@ -1,37 +0,0 @@ -// Given an array of integers, return indices of the two numbers such that they add up to a specific target. - -// You may assume that each input would have exactly one solution. - -// Example: -// Given nums = [2, 7, 11, 15], target = 9, - -// Because nums[0] + nums[1] = 2 + 7 = 9, -// return [0, 1]. -// UPDATE (2016/2/13): -// The return format had been changed to zero-based indices. Please read the above updated description carefully. - -// Hide Company Tags LinkedIn Uber Airbnb Facebook Amazon Microsoft Apple Yahoo Dropbox Bloomberg Yelp Adobe -// Hide Tags Array Hash Table -// Hide Similar Problems (M) 3Sum (M) 4Sum (M) Two Sum II - Input array is sorted (E) Two Sum III - Data structure design - - - -/** - * @param {number[]} nums - * @param {number} target - * @return {number[]} - */ -var twoSum = function(nums, target) { - var hash = {}; - - for(var i = 0; i < nums.length; i++) { - var num = nums[i]; - if(hash[num] !== undefined) { - return [hash[num], i] - } else { - hash[target - num] = i; - } - } - - return []; -}; \ No newline at end of file diff --git a/10 Regular Expresion Matching.js b/10 Regular Expresion Matching.js deleted file mode 100644 index ca77413..0000000 --- a/10 Regular Expresion Matching.js +++ /dev/null @@ -1,73 +0,0 @@ -// https://www.youtube.com/watch?v=l3hda49XcDE#t=211.113333 - -// Implement regular expression matching with support for '.' and '*'. - -// '.' Matches any single character. -// '*' Matches zero or more of the preceding element. - -// The matching should cover the entire input string (not partial). - -// The function prototype should be: -// bool isMatch(const char *s, const char *p) - -// Some examples: -// isMatch("aa","a") → false -// isMatch("aa","aa") → true -// isMatch("aaa","aa") → false -// isMatch("aa", "a*") → true -// isMatch("aa", ".*") → true -// isMatch("ab", ".*") → true -// isMatch("aab", "c*a*b") → true - -/** - * @param {string} s - * @param {string} p - * @return {boolean} - */ -var isMatch = function(s, p) { - var sLen = s.length; - var pLen = p.length; - var dp = []; - - for(var i = 0; i <= sLen; i++) { - var tmp = []; - - for(var j = 0; j <= pLen; j++) { - tmp.push(false); - } - - dp.push(tmp); - } - - dp[0][0] = true; - - for(i = 0; i <= sLen; i++) { - for(j = 0; j <= pLen; j++) { - if(p[j - 1] !== '.' && p[j - 1] !== '*') { - if(i > 0 && p[j - 1] === s[i - 1] && dp[i - 1][j - 1]) { - dp[i][j] = true; - } - } else if(p[j - 1] === '.') { - if(i > 0 && dp[i - 1][j - 1]) { - dp[i][j] = true; - } - } else if(j > 1) { // '*' cannot be the first element - if(dp[i][j - 2]) { // 0 occurance - dp[i][j] = true; - } else if(i > 0 && (p[j - 2] === s[i - 1] || p[j - 2] === '.') && dp[i - 1][j]) { - - // example - // xa and xa* - // s[i-1] === a - // p[j-2] === a - // a === a - // so we can now compare x, xa* - // and x here is dp[i-1][j] - dp[i][j] = true; - } - } - } - } - - return dp[sLen][pLen]; -}; \ 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 From 9fa76794755eb1a0470b85087387333e1cb5cb1c Mon Sep 17 00:00:00 2001 From: Chihung Yu Date: Sat, 22 Jun 2019 12:29:35 -0700 Subject: [PATCH 04/10] update --- [0001] Two Sum.js | 37 ++++++++++++++ [0002] Add Two Numbers.js | 55 +++++++++++++++++++++ [0010] Regular Expresion Matching.js | 73 ++++++++++++++++++++++++++++ 3 files changed, 165 insertions(+) create mode 100644 [0001] Two Sum.js create mode 100644 [0002] Add Two Numbers.js create mode 100644 [0010] Regular Expresion Matching.js diff --git a/[0001] Two Sum.js b/[0001] Two Sum.js new file mode 100644 index 0000000..ed67bd0 --- /dev/null +++ b/[0001] Two Sum.js @@ -0,0 +1,37 @@ +// Given an array of integers, return indices of the two numbers such that they add up to a specific target. + +// You may assume that each input would have exactly one solution. + +// Example: +// Given nums = [2, 7, 11, 15], target = 9, + +// Because nums[0] + nums[1] = 2 + 7 = 9, +// return [0, 1]. +// UPDATE (2016/2/13): +// The return format had been changed to zero-based indices. Please read the above updated description carefully. + +// Hide Company Tags LinkedIn Uber Airbnb Facebook Amazon Microsoft Apple Yahoo Dropbox Bloomberg Yelp Adobe +// Hide Tags Array Hash Table +// Hide Similar Problems (M) 3Sum (M) 4Sum (M) Two Sum II - Input array is sorted (E) Two Sum III - Data structure design + + + +/** + * @param {number[]} nums + * @param {number} target + * @return {number[]} + */ +var twoSum = function(nums, target) { + var hash = {}; + + for(var i = 0; i < nums.length; i++) { + var num = nums[i]; + if(hash[num] !== undefined) { + return [hash[num], i] + } else { + hash[target - num] = i; + } + } + + return []; +}; \ No newline at end of file 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/[0010] Regular Expresion Matching.js b/[0010] Regular Expresion Matching.js new file mode 100644 index 0000000..ca77413 --- /dev/null +++ b/[0010] Regular Expresion Matching.js @@ -0,0 +1,73 @@ +// https://www.youtube.com/watch?v=l3hda49XcDE#t=211.113333 + +// Implement regular expression matching with support for '.' and '*'. + +// '.' Matches any single character. +// '*' Matches zero or more of the preceding element. + +// The matching should cover the entire input string (not partial). + +// The function prototype should be: +// bool isMatch(const char *s, const char *p) + +// Some examples: +// isMatch("aa","a") → false +// isMatch("aa","aa") → true +// isMatch("aaa","aa") → false +// isMatch("aa", "a*") → true +// isMatch("aa", ".*") → true +// isMatch("ab", ".*") → true +// isMatch("aab", "c*a*b") → true + +/** + * @param {string} s + * @param {string} p + * @return {boolean} + */ +var isMatch = function(s, p) { + var sLen = s.length; + var pLen = p.length; + var dp = []; + + for(var i = 0; i <= sLen; i++) { + var tmp = []; + + for(var j = 0; j <= pLen; j++) { + tmp.push(false); + } + + dp.push(tmp); + } + + dp[0][0] = true; + + for(i = 0; i <= sLen; i++) { + for(j = 0; j <= pLen; j++) { + if(p[j - 1] !== '.' && p[j - 1] !== '*') { + if(i > 0 && p[j - 1] === s[i - 1] && dp[i - 1][j - 1]) { + dp[i][j] = true; + } + } else if(p[j - 1] === '.') { + if(i > 0 && dp[i - 1][j - 1]) { + dp[i][j] = true; + } + } else if(j > 1) { // '*' cannot be the first element + if(dp[i][j - 2]) { // 0 occurance + dp[i][j] = true; + } else if(i > 0 && (p[j - 2] === s[i - 1] || p[j - 2] === '.') && dp[i - 1][j]) { + + // example + // xa and xa* + // s[i-1] === a + // p[j-2] === a + // a === a + // so we can now compare x, xa* + // and x here is dp[i-1][j] + dp[i][j] = true; + } + } + } + } + + return dp[sLen][pLen]; +}; \ No newline at end of file From 115eeff08d94c40cc6568a1e321d26712b701742 Mon Sep 17 00:00:00 2001 From: Chihung Yu Date: Sat, 22 Jun 2019 15:07:37 -0700 Subject: [PATCH 05/10] update --- ...js => [0003] Longest Substring Without Repeating Characters.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename 3 Longest Substring Without Repeating Characters.js => [0003] Longest Substring Without Repeating Characters.js (100%) diff --git a/3 Longest Substring Without Repeating Characters.js b/[0003] Longest Substring Without Repeating Characters.js similarity index 100% rename from 3 Longest Substring Without Repeating Characters.js rename to [0003] Longest Substring Without Repeating Characters.js From aa9af43396cce8024e43b3bd11d6a2eec5181e7d Mon Sep 17 00:00:00 2001 From: Chihung Yu Date: Sun, 23 Jun 2019 18:03:33 -0700 Subject: [PATCH 06/10] update --- 4. Median of Two Sorted Arrays.js | 94 ------------------------------- 1 file changed, 94 deletions(-) delete mode 100644 4. Median of Two Sorted Arrays.js 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 From 40e026aa3550a3b9d3f9260517f533425e6fc4d1 Mon Sep 17 00:00:00 2001 From: Chihung Yu Date: Wed, 11 Mar 2020 09:15:52 -0700 Subject: [PATCH 07/10] add comment --- 11 Container With Most Water.js | 34 +++++++-- 31 Next Permutation.js | 56 ++++++++++++++- 55 Jump Game.js | 3 +- 76 Minimum Window Substring.js | 71 ++++++++++++++++++- ... Substring Without Repeating Characters.js | 3 + 5 files changed, 157 insertions(+), 10 deletions(-) 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/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/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/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/[0003] Longest Substring Without Repeating Characters.js b/[0003] Longest Substring Without Repeating Characters.js index 41f4575..d917b15 100644 --- a/[0003] 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; From dbcd8175871598a72c9f533c8c63ce597cf649e6 Mon Sep 17 00:00:00 2001 From: Chihung Yu Date: Wed, 11 Mar 2020 22:44:12 -0700 Subject: [PATCH 08/10] p1 --- ...g with At Most Two Disctinct Characters.js | 48 +++++++++++++++++-- 48 Rotate Image.js | 39 +++++++++++++++ 2 files changed, 84 insertions(+), 3 deletions(-) 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..19b9ca3 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,43 @@ 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) { + curStr = s.substring(start, i); + 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/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 From b517b1a4b6ae3abfd009a7095f167eee6653968b Mon Sep 17 00:00:00 2001 From: Chihung Yu Date: Thu, 12 Mar 2020 21:50:36 -0700 Subject: [PATCH 09/10] update --- 15 3Sum.js | 4 +-- ...ers Give Read4 II - Call Multiple Times.js | 33 +++++++++++++++++++ ...g with At Most Two Disctinct Characters.js | 1 - 66 Plus One.js | 29 ++++++++++++++++ 4 files changed, 64 insertions(+), 3 deletions(-) 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 19b9ca3..aae47ba 100644 --- a/159 Longest Substring with At Most Two Disctinct Characters.js +++ b/159 Longest Substring with At Most Two Disctinct Characters.js @@ -64,7 +64,6 @@ var lengthOfLongestSubstringTwoDistinct = function(s) { if (map.size === 2 && map.get(c) === undefined) { var curStr; if (i - start > maxLen) { - curStr = s.substring(start, i); maxLen = i - start; } var leftMost = s.length; 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]; From fba8bd482360cbc3283169a5cde122e4ac39d2e9 Mon Sep 17 00:00:00 2001 From: Chihung Yu Date: Thu, 12 Mar 2020 21:51:33 -0700 Subject: [PATCH 10/10] update --- 163 Missing Ranges.js | 39 +++ 681 Next Closest Time .js | 75 ++++++ [0004] Median of Two Sorted Arrays.js | 146 +++++++++++ ...ian of Two Sorted Arrays.sublime-workspace | 239 ++++++++++++++++++ key concepts | 3 + 5 files changed, 502 insertions(+) create mode 100644 163 Missing Ranges.js create mode 100644 681 Next Closest Time .js create mode 100644 [0004] Median of Two Sorted Arrays.js create mode 100644 [0004] Median of Two Sorted Arrays.sublime-workspace create mode 100644 key concepts 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/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/[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/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 +