From 57045d7772c5476f99d550c130da2394bf318017 Mon Sep 17 00:00:00 2001 From: yige Date: Mon, 18 May 2020 00:43:15 +0800 Subject: [PATCH] =?UTF-8?q?add:=20=E9=AA=8C=E8=AF=81=E5=9B=9E=E6=96=87?= =?UTF-8?q?=E5=AD=97=E7=AC=A6=E4=B8=B2=20=E2=85=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/settings.json | 3 ++ README.md | 28 +++++++++++++--- src/array/maximum-product-subarray.js | 18 ++++++++++ src/graphs/course-schedule-ii.js | 34 +++++++++++++++++++ src/string/valid-palindrome-ii.js | 37 +++++++++++++++++++++ test/array/maximum-product-subarray.test.js | 6 ++++ test/graphs/course-schedule-ii.test.js | 6 ++++ test/string/valid-palindrome-ii.test.js | 8 +++++ 8 files changed, 135 insertions(+), 5 deletions(-) create mode 100644 src/array/maximum-product-subarray.js create mode 100644 src/graphs/course-schedule-ii.js create mode 100644 src/string/valid-palindrome-ii.js create mode 100644 test/array/maximum-product-subarray.test.js create mode 100644 test/graphs/course-schedule-ii.test.js create mode 100644 test/string/valid-palindrome-ii.test.js diff --git a/.vscode/settings.json b/.vscode/settings.json index c8dd357..7e11d96 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,8 @@ { "cSpell.words": [ + "Gitpod", "LVIII", + "Prinme", "abcdefg", "cdefgab", "chuan", @@ -15,6 +17,7 @@ "powx", "pwwkew", "subarray", + "subarrays", "umghlrlose", "xuan", "zhong", diff --git a/README.md b/README.md index 7ccb774..96cdfa1 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,11 @@ LeetCode 与 LintCode 解题记录。此为个人练习仓库,代码中对重 - LeetCode 13. 罗马数字转整数 - LintCode 419. 罗马数字转整数 +- [验证回文字符串 Ⅱ](src/string/valid-palindrome-ii.js) + + - LeetCode 680. 验证回文字符串 Ⅱ + - LintCode 891. 有效回文 II + ## 数组/队列/集合/映射 - [电话号码的字母组合](src/array/letter-combinations-of-a-phone-number.js) @@ -293,6 +298,11 @@ LeetCode 与 LintCode 解题记录。此为个人练习仓库,代码中对重 - LeetCode 387. 字符串中的第一个唯一字符 - LintCode 209. 第一个只出现一次的字符 +- [乘积最大子数组](src/array/maximum-product-subarray.js) + + - LeetCode 152. 乘积最大子数组 + - LintCode 191. 乘积最大子序列 + ## 栈 - [最大矩阵](src/stack/maximal-rectangle.js) @@ -333,17 +343,17 @@ LeetCode 与 LintCode 解题记录。此为个人练习仓库,代码中对重 - [回文数](src/math/palindrome-number.js) - LeetCode 9. 回文数 - - LintCode 491. 回文数 + - LintCode 491. 回文数 - [Pow(x, n)](src/math/powx-n.js) - LeetCode 50. Pow(x, n) - - LintCode 428. x的n次幂 + - LintCode 428. x的n次幂 - [和为K的子数组](src/math/subarray-sum-equals-k.js) - LeetCode 560. 和为K的子数组 - - LintCode 838. 子数组和为K + - LintCode 838. 子数组和为K ## 堆 @@ -362,7 +372,7 @@ LeetCode 与 LintCode 解题记录。此为个人练习仓库,代码中对重 - [验证二叉搜索树](src/tree/validate-binary-search-tree.js) - LeetCode 98. 验证二叉搜索树 - - LintCode 95. 验证二叉查找树 + - LintCode 95. 验证二叉查找树 - [二叉树的最近公共祖先](src/tree/lowest-common-ancestor-of-a-binary-tree.js) @@ -415,4 +425,12 @@ LeetCode 与 LintCode 解题记录。此为个人练习仓库,代码中对重 - [K个一组翻转链表](src/list/reverse-nodes-in-k-group.js) - LeetCode 25. K 个一组翻转链表 - - LintCode 450. K组翻转链表 + - LintCode 450. K组翻转链表 + +## 图 + +- [课程表](src/graphs/course-schedule-ii.js) + + - LeetCode 210. 课程表 II + - LeetCode 207. 课程表 + - LintCode 615. 课程表 diff --git a/src/array/maximum-product-subarray.js b/src/array/maximum-product-subarray.js new file mode 100644 index 0000000..cbaee4f --- /dev/null +++ b/src/array/maximum-product-subarray.js @@ -0,0 +1,18 @@ +/** + * @param {number[]} nums + * @return {number} + */ +export const maxProduct = function (nums) { + let res = nums[0] + let prevMin = nums[0] + let prevMax = nums[0] + let tmp1 = 0; let tmp2 = 0 + for (let i = 1; i < nums.length; i++) { + tmp1 = prevMin * nums[i] + tmp2 = prevMax * nums[i] + prevMin = Math.min(tmp1, tmp2, nums[i]) + prevMax = Math.max(tmp1, tmp2, nums[i]) + res = Math.max(prevMax, res) + } + return res +} diff --git a/src/graphs/course-schedule-ii.js b/src/graphs/course-schedule-ii.js new file mode 100644 index 0000000..a786dd8 --- /dev/null +++ b/src/graphs/course-schedule-ii.js @@ -0,0 +1,34 @@ +/** + * @param {number} numCourses + * @param {number[][]} prerequisites + * @return {number[]} + */ +export const findOrder = function (numCourses, prerequisites) { + const courses = Array(numCourses).fill(0) // 初始化 上课 需要先完成课程 的门数 + const obj = {} // 记录受该课程 影响的其他课 + prerequisites.forEach(item => { + const one = item[0]; const two = item[1] // one 要上的课, two 需先完成的课 + courses[one]++ // 门数 + 1 + obj[two] ? obj[two].push(one) : obj[two] = [one] // 存在就加, 不存在就新建 + }) + const res = [] + const queue = [] // 队列 + courses.forEach((t, i) => { // 往队列添加 无需先上 就可以 上 的课 + if (t === 0) queue.push(i) // 因为是从0开始的, 所以索引也能代替 课的名称 + }) + while (queue.length) { + const cur = queue.shift() // 出队 表示该课已经上了 + res.push(cur) // 把出队的放入 结果数组 + const list = obj[cur] // 获取受该课影响的 课 + list && list.forEach(item => { + courses[item]-- // 因为 出队表示该课已经上了, 所以 要先完成的门数 - 1 + if (courses[item] === 0) { // 当这个课 要先修完的 已经修完了, 入队 + queue.push(item) + } + }) + } + + return res.length === numCourses ? res : [] +} + +// 参考自 https://leetcode-cn.com/problems/course-schedule-ii/solution/chao-da-an-by-shetia/ diff --git a/src/string/valid-palindrome-ii.js b/src/string/valid-palindrome-ii.js new file mode 100644 index 0000000..6713d69 --- /dev/null +++ b/src/string/valid-palindrome-ii.js @@ -0,0 +1,37 @@ +/** + * @param {string} s + * @return {boolean} + */ +export const validPalindrome = function (s, flag = true) { + let l = 0; let r = s.length - 1 + while (l < r && s[l] === s[r]) { + l++; r-- + } + if (l >= r) return true // 说明是回文 + if (flag) return validPalindrome(s.slice(l, r), false) || validPalindrome(s.slice(l + 1, r + 1), false) // 如果不是回文,切左边或者右边,再判断一次 + return false +} + +// 暴力解法,会超时 +// /** +// * @param {string} s +// * @return {boolean} +// */ +// export const validPalindrome = function (s) { +// const len = s.length +// const tmpLen = len - 1 +// let mid = len >> 1 +// if (s.substring(0, mid) === s.substring(len % 2 ? mid + 1 : mid, len).split('').reverse().join('')) { +// return true +// } + +// mid = tmpLen >> 1 +// for (let n = 0; n < len; n++) { +// const tmp = s.substring(0, n) + s.substring(n + 1, len) +// if (tmp.substring(0, mid) === tmp.substring(tmpLen % 2 ? mid + 1 : mid, tmpLen).split('').reverse().join('')) { +// return true +// } +// } + +// return false +// } diff --git a/test/array/maximum-product-subarray.test.js b/test/array/maximum-product-subarray.test.js new file mode 100644 index 0000000..fc96c07 --- /dev/null +++ b/test/array/maximum-product-subarray.test.js @@ -0,0 +1,6 @@ +import { maxProduct } from '../../src/array/maximum-product-subarray' + +test('', () => { + expect(maxProduct([2, 3, -2, 4])).toBe(6) + expect(maxProduct([-2, 0, -1])).toBe(0) +}) diff --git a/test/graphs/course-schedule-ii.test.js b/test/graphs/course-schedule-ii.test.js new file mode 100644 index 0000000..92a19b2 --- /dev/null +++ b/test/graphs/course-schedule-ii.test.js @@ -0,0 +1,6 @@ +import { findOrder } from '../../src/graphs/course-schedule-ii' + +test('课程表 II', () => { + expect(findOrder(2, [[1, 0]])).toEqual([0, 1]) + expect(findOrder(4, [[1, 0], [2, 0], [3, 1], [3, 2]])).toEqual([0, 1, 2, 3]) +}) diff --git a/test/string/valid-palindrome-ii.test.js b/test/string/valid-palindrome-ii.test.js new file mode 100644 index 0000000..ab25162 --- /dev/null +++ b/test/string/valid-palindrome-ii.test.js @@ -0,0 +1,8 @@ +import { validPalindrome } from '../../src/string/valid-palindrome-ii' + +test('验证回文字符串 Ⅱ', () => { + expect(validPalindrome('aba')).toBe(true) + expect(validPalindrome('abba')).toBe(true) + expect(validPalindrome('abca')).toBe(true) + expect(validPalindrome('abcda')).toBe(false) +})