Compare commits

...

59 Commits

Author SHA1 Message Date
20f821a921 add: 不同的二叉搜索树 2020-07-15 12:23:07 +08:00
2e60e7aa98 fix: 修改ci的配置 2020-07-06 12:06:59 +08:00
69986d68fd add: 将有序数组转换为二叉搜索树 2020-07-06 11:47:36 +08:00
7f6439ce7c add: 将有序数组转换为二叉搜索树 2020-07-06 11:41:53 +08:00
41aa639602 add: 将有序数组转换为二叉搜索树 2020-07-06 10:59:54 +08:00
146b33a651 add: 将有序数组转换为二叉搜索树 2020-07-06 10:59:02 +08:00
450f1f6b5d backup 2020-07-03 15:20:06 +08:00
89d8ac5e58 add: 有序矩阵中第K小的元素 2020-07-02 11:36:45 +08:00
16ec46e003 add: 最长重复子数组 2020-07-01 18:10:39 +08:00
3115552b87 add: 用两个栈实现队列 2020-06-30 18:43:25 +08:00
cc5208bda0 用两个栈实现队列 2020-06-30 18:42:26 +08:00
ed223c4b54 add: 二进制求和 2020-06-23 13:53:18 +08:00
e5a2f13ee2 二进制求和 2020-06-23 13:52:47 +08:00
fb6131a64e add: 三数之和 2020-06-12 14:50:11 +08:00
ada2de5c1a add: 每日温度 2020-06-11 15:33:28 +08:00
4fca08df37 update: 除自身以外数组的乘积 2020-06-04 15:49:27 +08:00
fbe2ab8fb8 update: 除自身以外数组的乘积 2020-06-04 15:43:16 +08:00
8da050ef53 add: 除自身以外数组的乘积 2020-06-04 15:40:47 +08:00
4aa8eba735 add: 拥有最多糖果的孩子 2020-06-01 17:34:40 +08:00
46dc5e9b3d 打家劫舍 2020-05-29 11:26:44 +08:00
95ca64dc6c add: 字符串解码 2020-05-28 11:01:35 +08:00
a69362984c update: 和可被K整除的子数组 2020-05-27 10:24:50 +08:00
596ae26ade add: 和可被K整除的子数组 2020-05-27 10:19:18 +08:00
6098f48863 add: 寻找重复数 2020-05-26 23:27:04 +08:00
3770b30040 add: LRU缓存机制 2020-05-25 22:27:39 +08:00
06d357b002 add: 柠檬水找零 2020-05-24 23:46:31 +08:00
8ca4a189f8 add: 最长公共前缀 2020-05-24 19:42:58 +08:00
581a96e795 add: 寻找两个正序数组的中位数 2020-05-24 19:16:28 +08:00
c371738884 add: 定长子串中元音的最大数目 2020-05-24 12:38:29 +08:00
5c5f35c535 add: 检查单词是否为句中其他单词的前缀 2020-05-24 12:34:13 +08:00
4940ceaeb9 update: 最小覆盖子串 2020-05-23 22:58:32 +08:00
b710fc166d add: 最小覆盖子串 2020-05-23 22:56:11 +08:00
3395b76309 Merge branch 'master' of git.hxr.so:yige/js-practice 2020-05-22 21:25:06 +08:00
a2ccc4764b add: 最长回文字符串 2020-05-22 21:25:03 +08:00
6a8d487f93 add: 完美数 2020-05-22 16:21:33 +08:00
bf6f71f55f add: 从前序与中序遍历序列构造二叉树 2020-05-22 15:40:53 +08:00
2120bcdecf add: 每个元音包含偶数次的最长子字符串 2020-05-21 00:08:57 +08:00
32fd589c3f IP地址无效化 2020-05-20 16:08:32 +08:00
34a76e22b9 add: 最高频率的IP 2020-05-20 16:00:09 +08:00
57045d7772 add: 验证回文字符串 Ⅱ 2020-05-20 15:28:29 +08:00
95c8f9aac2 update: K个一组翻转链表 2020-05-16 21:08:49 +08:00
a3c4f1b9fc update: K个一组翻转链表 2020-05-16 20:46:41 +08:00
55ff39a1c3 add: K个一组翻转链表 2020-05-16 19:50:31 +08:00
5593f3e2c7 add: 和为K的子数组 2020-05-15 19:25:33 +08:00
d348c63824 add: 第一个只出现一次的字符 2020-05-14 18:26:00 +08:00
9c2a165583 add: 数据流中第一个唯一的数字 2020-05-14 18:03:49 +08:00
8f84fc8c66 add: 二叉树的层序遍历 II 2020-05-13 14:59:02 +08:00
7ff3a150b7 update: 二叉树的层序遍历 2020-05-13 14:43:51 +08:00
f391e66174 Merge branch 'master' of git.hxr.so:yige/js-practice 2020-05-13 14:40:43 +08:00
f1564fe56d add: 二叉树的层序遍历 2020-05-13 14:40:04 +08:00
7055121867 add: 最小栈 2020-05-12 22:30:19 +08:00
36b0434402 add: Pow(x, n) 2020-05-11 17:06:20 +08:00
02a4031bd6 add: 罗马数字转整数 2020-05-10 18:41:04 +08:00
1cacc57721 add: 整数转罗马数字 2020-05-10 18:27:48 +08:00
6036e99c52 add: 最后一个单词的长度 2020-05-10 18:05:18 +08:00
8a69d1cfb0 add: 链表的中间节点 2020-05-10 16:57:42 +08:00
304866ecbf add: 回文数 2020-05-10 16:13:38 +08:00
da0e4f1359 add: 二叉树的最近公共祖先 2020-05-10 15:31:25 +08:00
64941ec538 add: 二叉树的最近公共祖先 2020-05-10 15:30:48 +08:00
96 changed files with 1939 additions and 216 deletions

View File

@ -5,27 +5,26 @@ name: Node.js CI
on: on:
push: push:
branches: [ master ] branches: [master]
pull_request: pull_request:
branches: [ master ] branches: [master]
jobs: jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
node-version: [10.x, 12.x] node-version: [12.x, 14.x]
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }} - name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1 uses: actions/setup-node@v1
with: with:
node-version: ${{ matrix.node-version }} node-version: ${{ matrix.node-version }}
- run: npm install -g yarn - run: npm install -g yarn
- run: yarn install - run: yarn install
- run: yarn test - run: yarn test
env: env:
CI: true CI: true

35
.vscode/settings.json vendored
View File

@ -1,18 +1,51 @@
{ {
"cSpell.words": [ "cSpell.words": [
"ADOBECODEBANC",
"Gitpod",
"LVIII",
"Paddr",
"Prinme",
"abcdefg", "abcdefg",
"abciiidef",
"cdefgab", "cdefgab",
"chuan", "chuan",
"defang",
"defanging",
"dvdf", "dvdf",
"eleetminicoworoep",
"inorder",
"lcci", "lcci",
"lcof", "lcof",
"lcov",
"leetcode",
"leetcodeisgreat",
"liang",
"lrloseumgh", "lrloseumgh",
"mincost", "mincost",
"nums", "nums",
"powx",
"preorder",
"pwwkew", "pwwkew",
"qian",
"racecar",
"strs",
"subarray",
"subarrays",
"umghlrlose", "umghlrlose",
"xuan", "xuan",
"zhan",
"zhong", "zhong",
"zhuan" "zhuan"
] ],
"standard.options": {
"globals": [
"$",
"jQuery",
"fetch"
],
"usePackageJson": true,
"env": {
"jest": true
}
}
} }

453
README.md
View File

@ -18,79 +18,130 @@ LeetCode 与 LintCode 解题记录。此为个人练习仓库,代码中对重
- [反转字符串中的单词](src/string/reverse-words-in-a-string.js) - [反转字符串中的单词](src/string/reverse-words-in-a-string.js)
- LeetCode 557. 反转字符串中的单词 III https://leetcode-cn.com/problems/reverse-words-in-a-string-iii/ - LeetCode 557. 反转字符串中的单词 III <https://leetcode-cn.com/problems/reverse-words-in-a-string-iii/>
- LintCode 1173. 反转字符串 III https://www.lintcode.com/problem/reverse-words-in-a-string-iii/description - LintCode 1173. 反转字符串 III <https://www.lintcode.com/problem/reverse-words-in-a-string-iii/description>
- [计数二进制子串](src/string/count-binary-substrings.js) - [计数二进制子串](src/string/count-binary-substrings.js)
- LeetCode 696. 计数二进制子串 https://leetcode-cn.com/problems/count-binary-substrings/ - LeetCode 696. 计数二进制子串 <https://leetcode-cn.com/problems/count-binary-substrings/>
- LintCode 1079. 连续子串计数 https://www.lintcode.com/problem/count-binary-substrings/description - LintCode 1079. 连续子串计数 <https://www.lintcode.com/problem/count-binary-substrings/description>
- [重复的子串](src/string/repeated-substring-pattern.js) - [重复的子串](src/string/repeated-substring-pattern.js)
- LeetCode 459. 重复的子字符串 https://leetcode-cn.com/problems/repeated-substring-pattern/ - LeetCode 459. 重复的子字符串 <https://leetcode-cn.com/problems/repeated-substring-pattern/>
- LintCode 1227. 重复的子串模式 https://www.lintcode.com/problem/repeated-substring-pattern/description - LintCode 1227. 重复的子串模式 <https://www.lintcode.com/problem/repeated-substring-pattern/description>
- [正则表达式匹配](src/string/regular-expression-matching.js) - [正则表达式匹配](src/string/regular-expression-matching.js)
- LeetCode 10. 正则表达式匹配 https://leetcode-cn.com/problems/regular-expression-matching/ - LeetCode 10. 正则表达式匹配 <https://leetcode-cn.com/problems/regular-expression-matching/>
- LintCode 154. 正则表达式匹配 https://www.lintcode.com/problem/regular-expression-matching/description - LintCode 154. 正则表达式匹配 <https://www.lintcode.com/problem/regular-expression-matching/description>
- [恢复 IP 地址](src/string/restore-ip-addresses.js) - [恢复 IP 地址](src/string/restore-ip-addresses.js)
- LeetCode 93. 复原 IP 地址 https://leetcode-cn.com/problems/restore-ip-addresses/ - LeetCode 93. 复原 IP 地址 <https://leetcode-cn.com/problems/restore-ip-addresses/>
- LintCode 426. 恢复 IP 地址 https://www.lintcode.com/problem/restore-ip-addresses/description - LintCode 426. 恢复 IP 地址 <https://www.lintcode.com/problem/restore-ip-addresses/description>
- [存在重复元素](src/string/contains-duplicate.js) - [存在重复元素](src/string/contains-duplicate.js)
- LeetCode 217. 存在重复元素 https://leetcode-cn.com/problems/contains-duplicate/ - LeetCode 217. 存在重复元素 <https://leetcode-cn.com/problems/contains-duplicate/>
- [判断字符串是否没有重复字符](src/string/unique-characters.js) - [判断字符串是否没有重复字符](src/string/unique-characters.js)
- LintCode 157. 判断字符串是否没有重复字符 https://www.lintcode.com/problem/unique-characters/description - LintCode 157. 判断字符串是否没有重复字符 <https://www.lintcode.com/problem/unique-characters/description>
- [比较字符串](src/string/compare-strings.js) - [比较字符串](src/string/compare-strings.js)
- LintCode 55. 比较字符串 https://www.lintcode.com/problem/compare-strings/description - LintCode 55. 比较字符串 <https://www.lintcode.com/problem/compare-strings/description>
- [最长无重复字符的子串](src/string/longest-substring-without-repeating-characters.js) - [最长无重复字符的子串](src/string/longest-substring-without-repeating-characters.js)
- LeetCode 3. 无重复字符的最长子串 https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/ - LeetCode 3. 无重复字符的最长子串 <https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/>
- LintCode 384. 最长无重复字符的子串 https://www.lintcode.com/problem/longest-substring-without-repeating-characters/description - LintCode 384. 最长无重复字符的子串 <https://www.lintcode.com/problem/longest-substring-without-repeating-characters/description>
- [最大数](src/string/largest-number.js) - [最大数](src/string/largest-number.js)
- LeetCode 179. 最大数 https://leetcode-cn.com/problems/largest-number/ - LeetCode 179. 最大数 <https://leetcode-cn.com/problems/largest-number/>
- LintCode 184. 最大数 https://www.lintcode.com/problem/largest-number/description - LintCode 184. 最大数 <https://www.lintcode.com/problem/largest-number/description>
- [实现string2int()函数](src/string/string2int.js) - [实现 string2int()函数](src/string/string2int.js)
- 面试题参考思路,不严谨实现 廖雪峰 不要使用JavaScript内置的parseInt()函数利用mapreduce操作实现一个string2int()函数。 https://www.liaoxuefeng.com/wiki/1022910821149312/1024322552460832 - 面试题参考思路,不严谨实现 廖雪峰 不要使用 JavaScript 内置的 parseInt()函数,利用 mapreduce 操作实现一个 string2int()函数。 <https://www.liaoxuefeng.com/wiki/1022910821149312/1024322552460832>
- [左旋转字符串](src/string/zuo-xuan-zhuan-zi-fu-chuan-lcof.js) - [左旋转字符串](src/string/zuo-xuan-zhuan-zi-fu-chuan-lcof.js)
- LeetCode 面试题58 - II. 左旋转字符串 https://leetcode-cn.com/problems/zuo-xuan-zhuan-zi-fu-chuan-lcof/ - LeetCode 面试题 58 - II. 左旋转字符串 <https://leetcode-cn.com/problems/zuo-xuan-zhuan-zi-fu-chuan-lcof/>
## 数组 - [最后一个单词的长度](src/string/length-of-last-word.js)
- LeetCode 58. 最后一个单词的长度 <https://leetcode-cn.com/problems/length-of-last-word/>
- LintCode 422. 最后一个单词的长度 <https://www.lintcode.com/problem/length-of-last-word/description>
- [整数转罗马数字](src/string/integer-to-roman.js)
- LeetCode 12. 整数转罗马数字 <https://leetcode-cn.com/problems/integer-to-roman/>
- LintCode 418. 整数转罗马数字 <https://www.lintcode.com/problem/integer-to-roman/description>
- [罗马数字转整数](src/string/roman-to-integer.js)
- LeetCode 13. 罗马数字转整数 <https://leetcode-cn.com/problems/roman-to-integer/>
- LintCode 419. 罗马数字转整数 <https://www.lintcode.com/problem/roman-to-integer/description>
- [验证回文字符串 Ⅱ](src/string/valid-palindrome-ii.js)
- LeetCode 680. 验证回文字符串 Ⅱ <https://leetcode-cn.com/problems/valid-palindrome-ii/>
- LintCode 891. 有效回文 II <https://www.lintcode.com/problem/valid-palindrome-ii/description>
- [IP 地址无效化](src/string/defanging-an-ip-address.js)
- LeetCode 1108. IP 地址无效化 <https://leetcode-cn.com/problems/defanging-an-ip-address/>
- [最长回文子串](src/string/longest-palindromic-substring.js)
- LeetCode 5. 最长回文子串 <https://leetcode-cn.com/problems/longest-palindromic-substring/>
- LintCode 200. 最长回文子串 <https://www.lintcode.com/problem/longest-palindromic-substring/>
- [每个元音包含偶数次的最长子字符串](src/string/find-the-longest-substring-containing-vowels-in-even-counts.js)
- LeetCode 1371. 每个元音包含偶数次的最长子字符串 <https://leetcode-cn.com/problems/find-the-longest-substring-containing-vowels-in-even-counts/>
- [最小覆盖子串](src/string/minimum-window-substring.js)
- LeetCode 76. 最小覆盖子串 <https://leetcode-cn.com/problems/minimum-window-substring/>
- LintCode 32. 最小子串覆盖 <https://www.lintcode.com/problem/minimum-window-substring/description>
- [检查单词是否为句中其他单词的前缀](src/string/check-if-a-word-occurs-as-a-prefix-of-any-word-in-a-sentence.js)
- LeetCode 5416. 检查单词是否为句中其他单词的前缀 <https://leetcode-cn.com/problems/check-if-a-word-occurs-as-a-prefix-of-any-word-in-a-sentence/>
- [定长子串中元音的最大数目](src/string/maximum-number-of-vowels-in-a-substring-of-given-length.js)
- LeetCode 5417. 定长子串中元音的最大数目 <https://leetcode-cn.com/problems/maximum-number-of-vowels-in-a-substring-of-given-length/>
- [最长公共前缀](src/string/longest-common-prefix.js)
- LeetCode 14. 最长公共前缀 <https://leetcode-cn.com/problems/longest-common-prefix/>
- LintCode 78. 最长公共前缀 <https://www.lintcode.com/problem/longest-common-prefix/description>
## 数组/队列/集合/映射
- [电话号码的字母组合](src/array/letter-combinations-of-a-phone-number.js) - [电话号码的字母组合](src/array/letter-combinations-of-a-phone-number.js)
- LeetCode 17. 电话号码的字母组合 https://leetcode-cn.com/problems/letter-combinations-of-a-phone-number/ - LeetCode 17. 电话号码的字母组合 <https://leetcode-cn.com/problems/letter-combinations-of-a-phone-number/>
- LintCode 425. 电话号码的字母组合 https://www.lintcode.com/problem/letter-combinations-of-a-phone-number/description - LintCode 425. 电话号码的字母组合 <https://www.lintcode.com/problem/letter-combinations-of-a-phone-number/description>
- [卡牌分组](src/array/x-of-a-kind-in-a-deck-of-cards.js) - [卡牌分组](src/array/x-of-a-kind-in-a-deck-of-cards.js)
- LeetCode 914. 卡牌分组 https://leetcode-cn.com/problems/x-of-a-kind-in-a-deck-of-cards/ - LeetCode 914. 卡牌分组 <https://leetcode-cn.com/problems/x-of-a-kind-in-a-deck-of-cards/>
- [删除排序数组中的重复项](src/array/remove-duplicates-from-sorted-array.js) - [删除排序数组中的重复项](src/array/remove-duplicates-from-sorted-array.js)
- LeetCode 26. 删除排序数组中的重复项 https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array/ - LeetCode 26. 删除排序数组中的重复项 <https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array/>
- LintCode 100. 删除排序数组中的重复数字 https://www.lintcode.com/problem/remove-duplicates-from-sorted-array/description - LintCode 100. 删除排序数组中的重复数字 <https://www.lintcode.com/problem/remove-duplicates-from-sorted-array/description>
- [能否种花](src/array/can-place-flowers.js) - [能否种花](src/array/can-place-flowers.js)
- LeetCode 605. 种花问题 https://leetcode-cn.com/problems/can-place-flowers/ - LeetCode 605. 种花问题 <https://leetcode-cn.com/problems/can-place-flowers/>
- LintCode 1138. 能否放置花 https://www.lintcode.com/problem/can-place-flowers/description - LintCode 1138. 能否放置花 <https://www.lintcode.com/problem/can-place-flowers/description>
- [循环升序数组](src/array/loop-asc-array.js) - [循环升序数组](src/array/loop-asc-array.js)
@ -108,17 +159,17 @@ LeetCode 与 LintCode 解题记录。此为个人练习仓库,代码中对重
- [循环数组中的环-暂无解](src/array/circular-array-loop.js) - [循环数组中的环-暂无解](src/array/circular-array-loop.js)
- LeetCode 457. 环形数组循环 https://leetcode-cn.com/problems/circular-array-loop/ - LeetCode 457. 环形数组循环 <https://leetcode-cn.com/problems/circular-array-loop/>
- LintCode 1229. 循环数组中的环 https://www.lintcode.com/problem/circular-array-loop/description - LintCode 1229. 循环数组中的环 <https://www.lintcode.com/problem/circular-array-loop/description>
- [格雷编码](src/array/gray-code.js) - [格雷编码](src/array/gray-code.js)
- LeetCode 89. 格雷编码 https://leetcode-cn.com/problems/gray-code/ - LeetCode 89. 格雷编码 <https://leetcode-cn.com/problems/gray-code/>
- LintCode 411. 格雷编码 https://www.lintcode.com/problem/gray-code/description - LintCode 411. 格雷编码 <https://www.lintcode.com/problem/gray-code/description>
- [数组划分](src/array/partition-array.js) - [数组划分](src/array/partition-array.js)
- LintCode 31. 数组划分 https://www.lintcode.com/problem/partition-array/description - LintCode 31. 数组划分 <https://www.lintcode.com/problem/partition-array/description>
- [冒泡排序](src/array/bubble-sort.js) - [冒泡排序](src/array/bubble-sort.js)
@ -126,222 +177,386 @@ LeetCode 与 LintCode 解题记录。此为个人练习仓库,代码中对重
- [按奇偶排序数组](src/array/sort-array-by-parity.js) - [按奇偶排序数组](src/array/sort-array-by-parity.js)
- LeetCode 922. 按奇偶排序数组 II https://leetcode-cn.com/problems/sort-array-by-parity-ii/ - LeetCode 922. 按奇偶排序数组 II <https://leetcode-cn.com/problems/sort-array-by-parity-ii/>
- [数组中的第 K 个最大元素](src/array/kth-largest-element-in-an-array.js) - [数组中的第 K 个最大元素](src/array/kth-largest-element-in-an-array.js)
- LeetCode 215. 数组中的第 K 个最大元素 https://leetcode-cn.com/problems/kth-largest-element-in-an-array/ - LeetCode 215. 数组中的第 K 个最大元素 <https://leetcode-cn.com/problems/kth-largest-element-in-an-array/>
- LeetCode 414. 第三大的数【相似,需去重】 https://leetcode-cn.com/problems/third-maximum-number/submissions/ - LeetCode 414. 第三大的数【相似,需去重】 <https://leetcode-cn.com/problems/third-maximum-number/submissions/>
- LintCode 5. 第 k 大元素 https://www.lintcode.com/problem/kth-largest-element/description - LintCode 5. 第 k 大元素 <https://www.lintcode.com/problem/kth-largest-element/description>
- LintCode 606. 第 K 大的元素 II https://www.lintcode.com/problem/kth-largest-element-ii/description - LintCode 606. 第 K 大的元素 II <https://www.lintcode.com/problem/kth-largest-element-ii/description>
- LintCode 544. 前 K 大数【相似】 https://www.lintcode.com/problem/top-k-largest-numbers/description - LintCode 544. 前 K 大数【相似】 <https://www.lintcode.com/problem/top-k-largest-numbers/description>
- LintCode 479. 数组第二大数【相似】 https://www.lintcode.com/problem/second-max-of-array/description - LintCode 479. 数组第二大数【相似】 <https://www.lintcode.com/problem/second-max-of-array/description>
- [最大间距](src/array/maximum-gap.js) - [最大间距](src/array/maximum-gap.js)
- LeetCode 164. 最大间距 https://leetcode-cn.com/problems/maximum-gap/ - LeetCode 164. 最大间距 <https://leetcode-cn.com/problems/maximum-gap/>
- LintCode 400. 最大间距 https://www.lintcode.com/problem/maximum-gap/ - LintCode 400. 最大间距 <https://www.lintcode.com/problem/maximum-gap/>
- [缺失的第一个正数](src/array/first-missing-positive.js) - [缺失的第一个正数](src/array/first-missing-positive.js)
- LeetCode 41. 缺失的第一个正数 https://leetcode-cn.com/problems/first-missing-positive/ - LeetCode 41. 缺失的第一个正数 <https://leetcode-cn.com/problems/first-missing-positive/>
- LintCode 189. 丢失的第一个正整数 https://www.lintcode.com/problem/first-missing-positive/description - LintCode 189. 丢失的第一个正整数 <https://www.lintcode.com/problem/first-missing-positive/description>
- LintCode 681. 缺失的第一个素数【相似】 https://www.lintcode.com/problem/first-missing-prime-number/description - LintCode 681. 缺失的第一个素数【相似】 <https://www.lintcode.com/problem/first-missing-prime-number/description>
- [缺失的第一个素数](src/array/first-missing-prime-number.js) - [缺失的第一个素数](src/array/first-missing-prime-number.js)
- LintCode 681. 缺失的第一个素数 https://www.lintcode.com/problem/first-missing-prime-number/description - LintCode 681. 缺失的第一个素数 <https://www.lintcode.com/problem/first-missing-prime-number/description>
- [串联所有单词的子串](src/array/substring-with-concatenation-of-all-words.js) - [串联所有单词的子串](src/array/substring-with-concatenation-of-all-words.js)
- LeetCode 30. 串联所有单词的子串 https://leetcode-cn.com/problems/substring-with-concatenation-of-all-words/ - LeetCode 30. 串联所有单词的子串 <https://leetcode-cn.com/problems/substring-with-concatenation-of-all-words/>
- LintCode 1362. 包含所有单词连接的子串 https://www.lintcode.com/problem/substring-with-concatenation-of-all-words/description - LintCode 1362. 包含所有单词连接的子串 <https://www.lintcode.com/problem/substring-with-concatenation-of-all-words/description>
- [买卖股票的最佳时机 II](src/array/best-time-to-buy-and-sell-stock-ii.js) - [买卖股票的最佳时机 II](src/array/best-time-to-buy-and-sell-stock-ii.js)
- LeetCode 122. 买卖股票的最佳时机 II https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii/ - LeetCode 122. 买卖股票的最佳时机 II <https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii/>
- LintCode 150. 买卖股票的最佳时机 II https://www.lintcode.com/problem/best-time-to-buy-and-sell-stock-ii/description - LintCode 150. 买卖股票的最佳时机 II <https://www.lintcode.com/problem/best-time-to-buy-and-sell-stock-ii/description>
- [搜索插入位置](src/array/search-insert-position.js) - [搜索插入位置](src/array/search-insert-position.js)
- LeetCode 35. 搜索插入位置 https://leetcode-cn.com/problems/search-insert-position/ - LeetCode 35. 搜索插入位置 <https://leetcode-cn.com/problems/search-insert-position/>
- LintCode 20. 搜索插入位置 https://www.lintcode.com/problem/search-insert-position/description - LintCode 20. 搜索插入位置 <https://www.lintcode.com/problem/search-insert-position/description>
- [二分查找](src/array/binary-search.js) - [二分查找](src/array/binary-search.js)
- LeetCode 35. 二分查找 https://leetcode-cn.com/problems/binary-search/ - LeetCode 35. 二分查找 <https://leetcode-cn.com/problems/binary-search/>
- LintCode 20. 二分查找 https://www.lintcode.com/problem/first-position-of-target/description - LintCode 20. 二分查找 <https://www.lintcode.com/problem/first-position-of-target/description>
- [查找常用字符](src/array/find-common-characters.js) - [查找常用字符](src/array/find-common-characters.js)
- LeetCode 1002. 查找常用字符 https://leetcode-cn.com/problems/find-common-characters/ - LeetCode 1002. 查找常用字符 <https://leetcode-cn.com/problems/find-common-characters/>
- [01 矩阵](src/array/01-matrix.js) - [01 矩阵](src/array/01-matrix.js)
- LeetCode 542. 01 矩阵 https://leetcode-cn.com/problems/01-matrix/ - LeetCode 542. 01 矩阵 <https://leetcode-cn.com/problems/01-matrix/>
- LintCode 974. 01 矩阵 https://www.lintcode.com/problem/01-matrix/description - LintCode 974. 01 矩阵 <https://www.lintcode.com/problem/01-matrix/description>
- [合并区间](src/array/merge-intervals.js) - [合并区间](src/array/merge-intervals.js)
- LeetCode 56. 合并区间 https://leetcode-cn.com/problems/merge-intervals/ - LeetCode 56. 合并区间 <https://leetcode-cn.com/problems/merge-intervals/>
- LintCode 156. 合并区间 https://www.lintcode.com/problem/merge-intervals/description - LintCode 156. 合并区间 <https://www.lintcode.com/problem/merge-intervals/description>
- [跳跃游戏](src/array/jump-game.js) - [跳跃游戏](src/array/jump-game.js)
- LeetCode 55. 跳跃游戏 https://leetcode-cn.com/problems/jump-game/ - LeetCode 55. 跳跃游戏 <https://leetcode-cn.com/problems/jump-game/>
- LintCode 116. 跳跃游戏 https://www.lintcode.com/problem/jump-game/description - LintCode 116. 跳跃游戏 <https://www.lintcode.com/problem/jump-game/description>
- [盛最多水的容器](src/array/container-with-most-water.js) - [盛最多水的容器](src/array/container-with-most-water.js)
- LeetCode 11. 盛最多水的容器 https://leetcode-cn.com/problems/container-with-most-water/ - LeetCode 11. 盛最多水的容器 <https://leetcode-cn.com/problems/container-with-most-water/>
- LintCode 383. 装最多水的容器 https://www.lintcode.com/problem/container-with-most-water/description - LintCode 383. 装最多水的容器 <https://www.lintcode.com/problem/container-with-most-water/description>
- [统计重复个数](src/array/count-the-repetitions.js) - [统计重复个数](src/array/count-the-repetitions.js)
- LeetCode 466. 统计重复个数 https://leetcode-cn.com/problems/count-the-repetitions/ - LeetCode 466. 统计重复个数 <https://leetcode-cn.com/problems/count-the-repetitions/>
- LintCode 1224. 统计重复个数 https://www.lintcode.com/problem/count-the-repetitions/description - LintCode 1224. 统计重复个数 <https://www.lintcode.com/problem/count-the-repetitions/description>
- [岛屿的个数](src/array/number-of-islands.js) - [岛屿的个数](src/array/number-of-islands.js)
- LeetCode 200. 岛屿数量 https://leetcode-cn.com/problems/number-of-islands/ - LeetCode 200. 岛屿数量 <https://leetcode-cn.com/problems/number-of-islands/>
- LintCode 433. 岛屿的个数 https://www.lintcode.com/problem/number-of-islands/description - LintCode 433. 岛屿的个数 <https://www.lintcode.com/problem/number-of-islands/description>
- [统计「优美子数组」](src/array/count-number-of-nice-subarrays.js) - [统计「优美子数组」](src/array/count-number-of-nice-subarrays.js)
- LeetCode 1248. 统计「优美子数组」 https://leetcode-cn.com/problems/count-number-of-nice-subarrays/ - LeetCode 1248. 统计「优美子数组」 <https://leetcode-cn.com/problems/count-number-of-nice-subarrays/>
- [主元素](src/array/majority-element.js) - [主元素](src/array/majority-element.js)
- LeetCode 面试题 17.10. 主要元素 https://leetcode-cn.com/problems/find-majority-element-lcci/ - LeetCode 面试题 17.10. 主要元素 <https://leetcode-cn.com/problems/find-majority-element-lcci/>
- LintCode 46. 主元素 https://www.lintcode.com/problem/majority-element/description - LintCode 46. 主元素 <https://www.lintcode.com/problem/majority-element/description>
- [逆序对](src/array/reverse-pairs.js) - [逆序对](src/array/reverse-pairs.js)
- LeetCode 面试题51. 数组中的逆序对 https://leetcode-cn.com/problems/shu-zu-zhong-de-ni-xu-dui-lcof/ - LeetCode 面试题 51. 数组中的逆序对 <https://leetcode-cn.com/problems/shu-zu-zhong-de-ni-xu-dui-lcof/>
- LintCode 532. 逆序对 https://www.lintcode.com/problem/reverse-pairs/description - LintCode 532. 逆序对 <https://www.lintcode.com/problem/reverse-pairs/description>
- [搜索旋转排序数组](src/array/search-in-rotated-sorted-array.js) - [搜索旋转排序数组](src/array/search-in-rotated-sorted-array.js)
- LeetCode 33. 搜索旋转排序数组 https://leetcode-cn.com/problems/search-in-rotated-sorted-array/ - LeetCode 33. 搜索旋转排序数组 <https://leetcode-cn.com/problems/search-in-rotated-sorted-array/>
- LintCode 62. 搜索旋转排序数组 https://www.lintcode.com/problem/search-in-rotated-sorted-array/description - LintCode 62. 搜索旋转排序数组 <https://www.lintcode.com/problem/search-in-rotated-sorted-array/description>
- [数组中数字出现的次数](src/array/shu-zu-zhong-shu-zi-chu-xian-de-ci-shu-lcof.js) - [数组中数字出现的次数](src/array/shu-zu-zhong-shu-zi-chu-xian-de-ci-shu-lcof.js)
- LeetCode 面试题56 - I. 数组中数字出现的次数 https://leetcode-cn.com/problems/shu-zu-zhong-shu-zi-chu-xian-de-ci-shu-lcof/ - LeetCode 面试题 56 - I. 数组中数字出现的次数 <https://leetcode-cn.com/problems/shu-zu-zhong-shu-zi-chu-xian-de-ci-shu-lcof/>
- [只出现一次的数字](src/array/single-number.js) - [只出现一次的数字](src/array/single-number.js)
- LeetCode 136. 只出现一次的数字 https://leetcode-cn.com/problems/single-number/ - LeetCode 136. 只出现一次的数字 <https://leetcode-cn.com/problems/single-number/>
- [山脉数组中查找目标值](src/array/find-in-mountain-array.js) - [山脉数组中查找目标值](src/array/find-in-mountain-array.js)
- LeetCode 1095. 山脉数组中查找目标值 https://leetcode-cn.com/problems/find-in-mountain-array/ - LeetCode 1095. 山脉数组中查找目标值 <https://leetcode-cn.com/problems/find-in-mountain-array/>
- LeetCode 852. 山脉数组的峰顶索引 https://leetcode-cn.com/problems/peak-index-in-a-mountain-array/ - LeetCode 852. 山脉数组的峰顶索引 <https://leetcode-cn.com/problems/peak-index-in-a-mountain-array/>
- LintCode 585. 山脉序列中的最大值 https://www.lintcode.com/problem/maximum-number-in-mountain-sequence/description - LintCode 585. 山脉序列中的最大值 <https://www.lintcode.com/problem/maximum-number-in-mountain-sequence/description>
- [快乐数](src/array/happy-number.js) - [快乐数](src/array/happy-number.js)
- LeetCode 202. 快乐数 https://leetcode-cn.com/problems/happy-number/ - LeetCode 202. 快乐数 <https://leetcode-cn.com/problems/happy-number/>
- LintCode 488. 快乐数 https://www.lintcode.com/problem/happy-number/description - LintCode 488. 快乐数 <https://www.lintcode.com/problem/happy-number/description>
- [最大子序和](src/array/maximum-subarray.js) - [最大子序和](src/array/maximum-subarray.js)
- LeetCode 53. 最大子序和 https://leetcode-cn.com/problems/maximum-subarray/ - LeetCode 53. 最大子序和 <https://leetcode-cn.com/problems/maximum-subarray/>
- LeetCode 面试题42. 连续子数组的最大和 https://leetcode-cn.com/problems/lian-xu-zi-shu-zu-de-zui-da-he-lcof/ - LeetCode 面试题 42. 连续子数组的最大和 <https://leetcode-cn.com/problems/lian-xu-zi-shu-zu-de-zui-da-he-lcof/>
- LintCode 41. 最大子数组 https://www.lintcode.com/problem/maximum-subarray/description - LintCode 41. 最大子数组 <https://www.lintcode.com/problem/maximum-subarray/description>
- [跳跃游戏II](src/array/jump-game-ii.js) - [跳跃游戏 II](src/array/jump-game-ii.js)
- LeetCode 45. 跳跃游戏 II https://leetcode-cn.com/problems/jump-game-ii/ - LeetCode 45. 跳跃游戏 II <https://leetcode-cn.com/problems/jump-game-ii/>
- LintCode 117. 跳跃游戏 II https://www.lintcode.com/problem/jump-game-ii/description - LintCode 117. 跳跃游戏 II <https://www.lintcode.com/problem/jump-game-ii/description>
- [最大数和最小数](src/array/maximum-and-minimum.js) - [最大数和最小数](src/array/maximum-and-minimum.js)
- LintCode 770. 最大数和最小数 https://www.lintcode.com/problem/maximum-and-minimum/description - LintCode 770. 最大数和最小数 <https://www.lintcode.com/problem/maximum-and-minimum/description>
- [最低票价](src/array/minimum-cost-for-tickets.js) - [最低票价](src/array/minimum-cost-for-tickets.js)
- LeetCode 983. 最低票价 https://leetcode-cn.com/problems/minimum-cost-for-tickets/ - LeetCode 983. 最低票价 <https://leetcode-cn.com/problems/minimum-cost-for-tickets/>
- [最大正方形](src/array/maximal-square.js) - [最大正方形](src/array/maximal-square.js)
- LeetCode 221. 最大正方形 https://leetcode-cn.com/problems/maximal-square/ - LeetCode 221. 最大正方形 <https://leetcode-cn.com/problems/maximal-square/>
- LintCode 436. 最大正方形 https://www.lintcode.com/problem/maximal-square/description - LintCode 436. 最大正方形 <https://www.lintcode.com/problem/maximal-square/description>
- [数据流中第一个唯一的数字](src/array/first-unique-number-in-data-stream.js)
- LintCode 685. 数据流中第一个唯一的数字 <https://www.lintcode.com/problem/first-unique-number-in-data-stream/description>
- [第一个只出现一次的字符](src/array/first-unique-character-in-a-string.js)
- LeetCode 面试题 50. 第一个只出现一次的字符 <https://leetcode-cn.com/problems/di-yi-ge-zhi-chu-xian-yi-ci-de-zi-fu-lcof/>
- LeetCode 387. 字符串中的第一个唯一字符 <https://leetcode-cn.com/problems/first-unique-character-in-a-string/>
- LintCode 209. 第一个只出现一次的字符 <https://www.lintcode.com/problem/first-unique-character-in-a-string/description>
- [乘积最大子数组](src/array/maximum-product-subarray.js)
- LeetCode 152. 乘积最大子数组 <https://leetcode-cn.com/problems/maximum-product-subarray/>
- LintCode 191. 乘积最大子序列 <https://www.lintcode.com/problem/maximum-product-subarray/description>
- [最高频率的 IP](src/array/highest-frequency-ip.js)
- LintCode 1613. 最高频率的 IP <https://www.lintcode.com/problem/highest-frequency-ip/description>
- [柠檬水找零](src/array/lemonade-change.js)
- LeetCode 860. 柠檬水找零 <https://leetcode-cn.com/problems/lemonade-change/>
- LintCode 1509. 柠檬水找零 <https://www.lintcode.com/problem/lemonade-change/description>
- [LRU 缓存机制](src/array/lru-cache.js)
- LeetCode 146. LRU 缓存机制 <https://leetcode-cn.com/problems/lru-cache/>
- LintCode 134. LRU 缓存策略 <https://www.lintcode.com/problem/lru-cache/description>
- [寻找重复数](src/array/find-the-duplicate-number.js)
- LeetCode 287. 寻找重复数 <https://leetcode-cn.com/problems/find-the-duplicate-number/>
- LintCode 633. 寻找重复的数 <https://www.lintcode.com/problem/find-the-duplicate-number/description>
- [和可被 K 整除的子数组](src/array/subarray-sums-divisible-by-k.js)
- LeetCode 974. 和可被 K 整除的子数组 <https://leetcode-cn.com/problems/subarray-sums-divisible-by-k/>
- [打家劫舍](src/array/house-robber.js)
- LeetCode 198. 打家劫舍 <https://leetcode-cn.com/problems/house-robber/>
- LintCode 392. 打劫房屋 <https://www.lintcode.com/problem/house-robber/description>
- [拥有最多糖果的孩子](src/array/kids-with-the-greatest-number-of-candies.js)
- LeetCode 1431. 拥有最多糖果的孩子 <https://leetcode-cn.com/problems/kids-with-the-greatest-number-of-candies/>
- [除自身以外数组的乘积](src/array/product-of-array-except-self.js)
- LeetCode 238. 除自身以外数组的乘积 <https://leetcode-cn.com/problems/product-of-array-except-self/>
- LintCode 1310. 数组除了自身的乘积 <https://www.lintcode.com/problem/product-of-array-except-self/description>
- [每日温度](src/array/daily-temperatures.js)
- LeetCode 739. 每日温度 <https://leetcode-cn.com/problems/daily-temperatures/>
- LintCode 1060. 每日温度 <https://www.lintcode.com/problem/daily-temperatures/description>
- [最长重复子数组](src/array/maximum-length-of-repeated-subarray.js)
- LeetCode 718. 最长重复子数组 <https://leetcode-cn.com/problems/maximum-length-of-repeated-subarray/>
- LintCode 79. 最长公共子串 <https://www.lintcode.com/problem/longest-common-substring/description>
- [有序矩阵中第 K 小的元素](src/array/kth-smallest-element-in-a-sorted-matrix.js)
- LeetCode 378. 有序矩阵中第 K 小的元素 <https://leetcode-cn.com/problems/kth-smallest-element-in-a-sorted-matrix/>
- LintCode 401. 排序矩阵中的从小到大第 k 个数 <https://www.lintcode.com/problem/kth-smallest-number-in-sorted-matrix/description>
## 栈 ## 栈
- [最大矩阵](src/stack/maximal-rectangle.js) - [最大矩阵](src/stack/maximal-rectangle.js)
- LeetCode 85. 最大矩阵 https://leetcode-cn.com/problems/maximal-rectangle/
- LintCode 510. 最大矩阵 https://www.lintcode.com/problem/maximal-rectangle/description - LeetCode 85. 最大矩阵 <https://leetcode-cn.com/problems/maximal-rectangle/>
- LintCode 510. 最大矩阵 <https://www.lintcode.com/problem/maximal-rectangle/description>
- [最小栈](src/stack/min-stack.js)
- LeetCode 155. 最小栈 <https://leetcode-cn.com/problems/min-stack/>
- LintCode 12. 带最小值操作的栈 <https://www.lintcode.com/problem/min-stack/description>
- [用两个栈实现队列](src/stack/yong-liang-ge-zhan-shi-xian-dui-lie-lcof.js)
- LeetCode 剑指 Offer 09. 用两个栈实现队列 <https://leetcode-cn.com/problems/yong-liang-ge-zhan-shi-xian-dui-lie-lcof/>
- [字符串解码](src/stack/decode-string.js)
- LeetCode 394. 字符串解码 <https://leetcode-cn.com/problems/decode-string/>
- LintCode 575. 字符串解码 <https://www.lintcode.com/problem/decode-string/description>
## 数学 ## 数学
- [阶乘后的零](src/math/factorial-trailing-zeroes.js) - [阶乘后的零](src/math/factorial-trailing-zeroes.js)
- LeetCode 172. 阶乘后的零 https://leetcode-cn.com/problems/factorial-trailing-zeroes/submissions/ - LeetCode 172. 阶乘后的零 <https://leetcode-cn.com/problems/factorial-trailing-zeroes/submissions/>
- LintCode 2. 尾部的零 https://www.lintcode.com/problem/trailing-zeros/description - LintCode 2. 尾部的零 <https://www.lintcode.com/problem/trailing-zeros/description>
- [丑数 II](src/math/ugly-number-ii.js) - [丑数 II](src/math/ugly-number-ii.js)
- LeetCode 264. 丑数 II https://leetcode-cn.com/problems/ugly-number-ii/ - LeetCode 264. 丑数 II <https://leetcode-cn.com/problems/ugly-number-ii/>
- LintCode 4. 丑数 II https://www.lintcode.com/problem/ugly-number-ii/description - LintCode 4. 丑数 II <https://www.lintcode.com/problem/ugly-number-ii/description>
- [面试题 08.11. 硬币](src/math/coin-lcci.js) - [面试题 08.11. 硬币](src/math/coin-lcci.js)
- LeetCode 面试题 08.11. 硬币 https://leetcode-cn.com/problems/coin-lcci/ - LeetCode 面试题 08.11. 硬币 <https://leetcode-cn.com/problems/coin-lcci/>
- [全排列](src/math/permutations.js) - [全排列](src/math/permutations.js)
- LeetCode 46. 全排列 https://leetcode-cn.com/problems/permutations/ - LeetCode 46. 全排列 <https://leetcode-cn.com/problems/permutations/>
- LintCode 15. 全排列 https://www.lintcode.com/problem/permutations/description - LintCode 15. 全排列 <https://www.lintcode.com/problem/permutations/description>
- [最大数值](src/math/maximum-lcci.js) - [最大数值](src/math/maximum-lcci.js)
- LeetCode 面试题 16.07. 最大数值 https://leetcode-cn.com/problems/maximum-lcci/ - LeetCode 面试题 16.07. 最大数值 <https://leetcode-cn.com/problems/maximum-lcci/>
- [回文数](src/math/palindrome-number.js)
- LeetCode 9. 回文数 <https://leetcode-cn.com/problems/palindrome-number/>
- LintCode 491. 回文数 <https://www.lintcode.com/problem/palindrome-number/description>
- [Pow(x, n)](src/math/powx-n.js)
- LeetCode 50. Pow(x, n) <https://leetcode-cn.com/problems/powx-n/>
- LintCode 428. x 的 n 次幂 <https://www.lintcode.com/problem/powx-n/description>
- [和为 K 的子数组](src/math/subarray-sum-equals-k.js)
- LeetCode 560. 和为 K 的子数组 <https://leetcode-cn.com/problems/subarray-sum-equals-k/>
- LintCode 838. 子数组和为 K <https://www.lintcode.com/problem/subarray-sum-equals-k/description>
- [完美数](src/math/perfect-number.js)
- LeetCode 507. 完美数 <https://leetcode-cn.com/problems/perfect-number/>
- LintCode 1199. 完美的数 <https://www.lintcode.com/problem/perfect-number/description>
- [寻找两个正序数组的中位数](src/math/median-of-two-sorted-arrays.js)
- LeetCode 4. 寻找两个正序数组的中位数 <https://leetcode-cn.com/problems/median-of-two-sorted-arrays/>
- LintCode 65. 两个排序数组的中位数 <https://www.lintcode.com/problem/median-of-two-sorted-arrays/description>
- [三数之和](src/math/3sum.js)
- LeetCode 15. 三数之和 <https://leetcode-cn.com/problems/3sum/>
- LintCode 57. 三数之和 <https://www.lintcode.com/problem/3sum/description>
- [二进制求和](src/math/add-binary.js)
- LeetCode 67. 二进制求和 <https://leetcode-cn.com/problems/add-binary/>
- LintCode 408. 二进制求和 <https://www.lintcode.com/problem/add-binary/description>
## 堆 ## 堆
- [超级丑数](src/stack/super-ugly-number.js)【未完成】 - [超级丑数](src/stack/super-ugly-number.js)【未完成】
- LeetCode 313. 超级丑数 https://leetcode-cn.com/problems/super-ugly-number/ - LeetCode 313. 超级丑数 <https://leetcode-cn.com/problems/super-ugly-number/>
- LintCode 518. 超级丑数 https://www.lintcode.com/problem/super-ugly-number/description - LintCode 518. 超级丑数 <https://www.lintcode.com/problem/super-ugly-number/description>
## 树 ## 树
- [二叉树的右视图](src/tree/binary-tree-right-side-view.js) - [二叉树的右视图](src/tree/binary-tree-right-side-view.js)
- LeetCode 199. 二叉树的右视图 https://leetcode-cn.com/problems/binary-tree-right-side-view/ - LeetCode 199. 二叉树的右视图 <https://leetcode-cn.com/problems/binary-tree-right-side-view/>
- LintCode 760. 二叉树的右视图 https://www.lintcode.com/problem/binary-tree-right-side-view/description - LintCode 760. 二叉树的右视图 <https://www.lintcode.com/problem/binary-tree-right-side-view/description>
- [验证二叉搜索树](src/tree/validate-binary-search-tree.js) - [验证二叉搜索树](src/tree/validate-binary-search-tree.js)
- LeetCode 98. 验证二叉搜索树 https://leetcode-cn.com/problems/validate-binary-search-tree/ - LeetCode 98. 验证二叉搜索树 <https://leetcode-cn.com/problems/validate-binary-search-tree/>
- LintCode 95. 验证二叉查找树 https://www.lintcode.com/problem/validate-binary-search-tree/ - LintCode 95. 验证二叉查找树 <https://www.lintcode.com/problem/validate-binary-search-tree/description>
- [二叉树的最近公共祖先](src/tree/lowest-common-ancestor-of-a-binary-tree.js)
- LeetCode 236. 二叉树的最近公共祖先 <https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree/>
- LintCode 88. 最近公共祖先 <https://www.lintcode.com/problem/lowest-common-ancestor-of-a-binary-tree/description>
- [另一个树的子树](src/tree/subtree-of-another-tree.js) - [另一个树的子树](src/tree/subtree-of-another-tree.js)
- LeetCode 572. 另一个树的子树 https://leetcode-cn.com/problems/subtree-of-another-tree/ - LeetCode 572. 另一个树的子树 <https://leetcode-cn.com/problems/subtree-of-another-tree/>
- LintCode 1165. 另一个树的子树 https://www.lintcode.com/problem/subtree-of-another-tree/description - LintCode 1165. 另一个树的子树 <https://www.lintcode.com/problem/subtree-of-another-tree/description>
- [二叉树的层序遍历](src/tree/binary-tree-level-order-traversal.js)
- LeetCode 102. 二叉树的层序遍历 <https://leetcode-cn.com/problems/binary-tree-level-order-traversal/>
- LintCode 69. 二叉树的层次遍历 <https://www.lintcode.com/problem/binary-tree-level-order-traversal/description>
- [二叉树的层次遍历 II](src/tree/binary-tree-level-order-traversal-ii.js)
- LeetCode 107. 二叉树的层次遍历 II <https://leetcode-cn.com/problems/binary-tree-level-order-traversal-ii/>
- LintCode 70. 二叉树的层次遍历 II <https://www.lintcode.com/problem/binary-tree-level-order-traversal-ii/description>
- [从前序与中序遍历序列构造二叉树](src/tree/construct-binary-tree-from-preorder-and-inorder-traversal.js)
- LeetCode 105. 从前序与中序遍历序列构造二叉树 <https://leetcode-cn.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/>
- LintCode 73. 前序遍历和中序遍历树构造二叉树 <https://www.lintcode.com/problem/construct-binary-tree-from-preorder-and-inorder-traversal/description>
- [将有序数组转换为二叉搜索树](src/tree/convert-sorted-array-to-binary-search-tree.js)
- LeetCode 108. 将有序数组转换为二叉搜索树 <https://leetcode-cn.com/problems/convert-sorted-array-to-binary-search-tree/>
- LintCode 106. 有序链表转换为二叉搜索树 <https://www.lintcode.com/problem/convert-sorted-list-to-binary-search-tree/description>
- [不同的二叉搜索树](src/tree/unique-binary-search-trees.js)
- LeetCode 96. 不同的二叉搜索树 <https://leetcode-cn.com/problems/unique-binary-search-trees/>
## 链表 ## 链表
- [合并K个排序链表](src/list/merge-k-sorted-lists.js) - [合并 K 个排序链表](src/list/merge-k-sorted-lists.js)
- LeetCode 23. 合并K个排序链表 https://leetcode-cn.com/problems/merge-k-sorted-lists/ - LeetCode 23. 合并 K 个排序链表 <https://leetcode-cn.com/problems/merge-k-sorted-lists/>
- LintCode 104. 合并k个排序链表 https://www.lintcode.com/problem/merge-k-sorted-lists/description - LintCode 104. 合并 k 个排序链表 <https://www.lintcode.com/problem/merge-k-sorted-lists/description>
- [合并两个有序链表](src/list/merge-two-sorted-lists.js) - [合并两个有序链表](src/list/merge-two-sorted-lists.js)
- LeetCode 21. 合并两个有序链表 https://leetcode-cn.com/problems/merge-two-sorted-lists/ - LeetCode 21. 合并两个有序链表 <https://leetcode-cn.com/problems/merge-two-sorted-lists/>
- LeetCode 面试题25. 合并两个排序的链表 https://leetcode-cn.com/problems/he-bing-liang-ge-pai-xu-de-lian-biao-lcof - LeetCode 面试题 25. 合并两个排序的链表 <https://leetcode-cn.com/problems/he-bing-liang-ge-pai-xu-de-lian-biao-lcof>
- LintCode 165. 合并两个排序链表 https://www.lintcode.com/problem/merge-two-sorted-lists/description - LintCode 165. 合并两个排序链表 <https://www.lintcode.com/problem/merge-two-sorted-lists/description>
- [链表排序](src/list/sort-list.js) - [链表排序](src/list/sort-list.js)
- LeetCode 148. 排序链表 https://leetcode-cn.com/problems/sort-list/ - LeetCode 148. 排序链表 <https://leetcode-cn.com/problems/sort-list/>
- LintCode 98. 链表排序 https://www.lintcode.com/problem/sort-list/description - LintCode 98. 链表排序 <https://www.lintcode.com/problem/sort-list/description>
- [环形链表](src/list/linked-list-cycle.js) - [环形链表](src/list/linked-list-cycle.js)
- LeetCode 141. 环形链表 https://leetcode-cn.com/problems/linked-list-cycle/ - LeetCode 141. 环形链表 <https://leetcode-cn.com/problems/linked-list-cycle/>
- LintCode 102. 带环链表 https://www.lintcode.com/problem/linked-list-cycle/description - LintCode 102. 带环链表 <https://www.lintcode.com/problem/linked-list-cycle/description>
- [链表的中间结点](src/list/middle-of-the-linked-list.js)
- LeetCode 876. 链表的中间结点 <https://leetcode-cn.com/problems/middle-of-the-linked-list/>
- LintCode 1609. 链表的中间结点 <https://www.lintcode.com/problem/middle-of-the-linked-list/description>
- [K 个一组翻转链表](src/list/reverse-nodes-in-k-group.js)
- LeetCode 25. K 个一组翻转链表 <https://leetcode-cn.com/problems/reverse-nodes-in-k-group/>
- LintCode 450. K 组翻转链表 <https://www.lintcode.com/problem/reverse-nodes-in-k-group/description>
## 图
- [课程表](src/graphs/course-schedule-ii.js)
- LeetCode 210. 课程表 II <https://leetcode-cn.com/problems/course-schedule-ii/>
- LeetCode 207. 课程表 <https://leetcode-cn.com/problems/course-schedule/>
- LintCode 615. 课程表 <https://www.lintcode.com/problem/course-schedule/description>

View File

@ -0,0 +1,18 @@
/**
* @param {number[]} T
* @return {number[]}
*/
export const dailyTemperatures = function (T) {
const len = T.length
const ans = new Array(len).fill(0)
const stack = []
for (let i = 0; i < len; i++) {
const temperature = T[i]
while (stack.length && temperature > T[stack[stack.length - 1]]) {
const prevIndex = stack.pop()
ans[prevIndex] = i - prevIndex
}
stack.push(i)
}
return ans
}

View File

@ -0,0 +1,24 @@
/**
* @param {number[]} nums
* @return {number}
*/
export const findDuplicate = function (nums) {
const len = nums.length
let l = 0; let r = len - 1; let res = -1 // 数字都在1-n
while (l <= r) {
const mid = (l + r) >> 1
let cnt = 0
for (let i = 0; i < len; i++) {
cnt += nums[i] <= mid // true = 1满足条件才计数
}
if (cnt <= mid) {
l = mid + 1
} else {
r = mid - 1
res = mid
}
}
return res
}

View File

@ -0,0 +1,18 @@
/**
* @param {string} s
* @return {character}
*/
export const firstUniqChar = function (s) {
const due = new Set()
const queue = new Set()
for (const n of s) {
if (queue.has(n)) {
queue.delete(n)
due.add(n)
} else if (!due.has(n)) {
queue.add(n)
}
}
return Array.from(queue)[0] || ' '
}

View File

@ -0,0 +1,23 @@
/**
* @param nums: a continuous stream of numbers
* @param number: a number
* @return: returns the first unique number
*/
export const firstUniqueNumber = function (nums, number) {
const due = new Set()
const queue = new Set()
for (const n of nums) {
if (queue.has(n)) {
queue.delete(n)
due.add(n)
} else if (!due.has(n)) {
queue.add(n)
}
if (n === number) break
}
if (!due.has(number) && !queue.has(number)) return -1
return Array.from(queue)[0] || -1
}

View File

@ -0,0 +1,19 @@
/**
* @param ipLines: ip address
* @return: return highestFrequency ip address
*/
export const highestFrequency = function (ipLines) {
const map = new Map()
let max = 0
let maxN = ipLines[0]
ipLines.forEach(n => {
const temp = (map.get(n) || 0) + 1
map.set(n, temp)
if (temp > max) {
maxN = n
max = temp
}
})
return maxN
}

18
src/array/house-robber.js Normal file
View File

@ -0,0 +1,18 @@
/**
* @param {number[]} nums
* @return {number}
*/
export const rob = function (nums) {
if (!nums) return 0
const len = nums.length
if (len === 0) return 0
if (len === 1) return nums[0]
let first = nums[0]; let second = Math.max(nums[0], nums[1])
for (let i = 2; i < len; i++) {
const temp = second
second = Math.max(first + nums[i], second)
first = temp
}
return second
}

View File

@ -0,0 +1,8 @@
/**
* @param {number[]} candies
* @param {number} extraCandies
* @return {boolean[]}
*/
export const kidsWithCandies = (candies, extraCandies) => {
return candies.map(n => n + extraCandies >= Math.max(...candies))
}

View File

@ -0,0 +1,8 @@
/**
* @param {number[][]} matrix
* @param {number} k
* @return {number}
*/
export const kthSmallest = function (matrix, k) {
return matrix.flat().sort((a, b) => a - b)[k - 1]
}

View File

@ -0,0 +1,31 @@
/**
* @param {number[]} bills
* @return {boolean}
*/
export const lemonadeChange = function (bills) {
const map = new Map()
while (bills.length) {
const money = bills.shift()
if (money === 5) {
map.set(5, (map.get(5) || 0) + 1)
} else {
let change = money - 5
while (change !== 0 && change - 10 > 0 && map.get(10) > 0) {
map.set(10, map.get(10) - 1)
change -= 10
}
while (change !== 0 && map.get(5) > 0) {
map.set(5, map.get(5) - 1)
change -= 5
}
if (change !== 0) return false
map.set(money, (map.get(money) || 0) + 1)
}
}
return true
}

21
src/array/lru-cache.js Normal file
View File

@ -0,0 +1,21 @@
export default class LRUCache {
constructor (capacity) {
this.max = capacity; this.map = new Map()
}
get (key) {
const value = this.map.get(key)
if (value !== undefined) {
this.map.delete(key)
this.map.set(key, value)
return value
}
return -1
}
put (key, value) {
this.map.delete(key)
this.map.set(key, value)
if (this.map.size > this.max) this.map.delete(this.map.keys().next().value)
}
}

View File

@ -0,0 +1,38 @@
// 输入:
// A: [1, 2, 3, 2, 1]
// B: [3, 2, 1, 4, 7]
const maxLength = function (A, B, addA, addB, len) {
addA = (addA > 0) ? addA : 0
addB = (addB > 0) ? addB : 0
let result = 0
let k = 0
for (let i = 0; i < len && (k + len - i > result); i++) {
if (A[i + addA] === B[i + addB]) {
k++
} else {
k = 0
}
result = Math.max(result, k)
}
return result
}
/**
* @param {number[]} A
* @param {number[]} B
* @return {number}
*/
export const findLength = function (A, B) {
const ALen = A.length
const BLen = B.length
let result = 0
for (let i = 1; i < ALen + BLen; i++) {
if (result >= (ALen + BLen - i)) {
return result
}
const len = Math.min(i, ALen, BLen, (ALen + BLen - i))
result = Math.max(maxLength(A, B, ALen - i, i - ALen, len), result)
}
return result
}

View File

@ -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
}

View File

@ -0,0 +1,23 @@
/**
* @param {number[]} nums
* @return {number[]}
*/
export const productExceptSelf = function (nums) {
const ans = []
for (let i = 0, len = nums.length; i < len; i++) {
let tmpL = 1
let tmpR = 1
for (let j = 0; j < len; j++) {
if (j < i) {
tmpL *= nums[j]
} else if (j > i) {
tmpR *= nums[j]
}
}
ans.push(tmpL * tmpR)
}
return ans
}
// 此算法效率不高,请勿仿照作者偷懒

View File

@ -0,0 +1,17 @@
/**
* @param {number[]} A
* @param {number} K
* @return {number}
*/
export const subarraysDivByK = function (A, K) {
const map = new Map([[0, 1]]); let sum = 0; let count = 0
A.forEach(n => {
sum = (sum + n) % K; sum = sum < 0 ? sum + K : sum
const temp = map.get(sum) || 0
count += temp
map.set(sum, temp + 1)
})
return count
}

View File

@ -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/

View File

@ -0,0 +1,25 @@
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
export const middleNode = function (head) {
if (!head.next) return head
if (head.next && !head.next.next) return head.next
let slow = head
let fast = head.next.next
while (fast.next && fast.next.next) {
slow = slow.next
fast = fast.next.next
}
return fast.next ? slow.next.next : slow.next
}

View File

@ -0,0 +1,48 @@
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @param {number} k
* @return {ListNode}
*/
export const reverseKGroup = function (head, k) {
// 《K个一组翻转链表》 https://www.wyr.me/post/622
let sum = 0 // 记录进行的结点个数
let start = head // 记录每次翻转的第一个元素
let res = head // 返回值:如果进行过翻转,则为第一次翻转的最后一个结点
const queue = [] // 使用队列方便连接上一次翻转的链表最大长度为2
while (head) { // 遍历一次链表
if (++sum === k) { // 如果经过了k个结点则翻转从start到head的一段结点
const headNext = head.next
queue.push(start) // 计入队列
let next = head.next
for (let i = 0; i < sum - 1; i++) { // 翻转结点
const tmp = start.next
start.next = next
next = start
start = tmp
}
start.next = next // 最后一个结点
if (queue.length === 1) { // 判断是否为第一次翻转
res = start
} else {
const la = queue.shift() // 连接上一次翻转的链表
la.next = head
}
sum = 0 // 重置计数
start = headNext
head = headNext
} else {
head = head.next
}
}
return res
}

31
src/math/3sum.js Normal file
View File

@ -0,0 +1,31 @@
// 一年前做过。复制自https://leetcode-cn.com/problems/3sum/solution/three-sum-ti-jie-by-wonderful611/
/**
* @param {number[]} nums
* @return {number[][]}
*/
export const threeSum = function (nums) {
const res = []
const length = nums.length
nums.sort((a, b) => a - b) // 先排个队,最左边是最弱(小)的,最右边是最强(大)的
if (nums[0] <= 0 && nums[length - 1] >= 0) { // 优化1: 整个数组同符号,则无解
for (let i = 0; i < length - 2;) {
if (nums[i] > 0) break // 优化2: 最左值为正数则一定无解
let first = i + 1
let last = length - 1
do {
if (first >= last || nums[i] * nums[last] > 0) break // 两人选相遇,或者三人同符号,则退出
const result = nums[i] + nums[first] + nums[last]
if (result === 0) { // 如果可以组队
res.push([nums[i], nums[first], nums[last]])
}
if (result <= 0) { // 实力太弱,把菜鸟那边右移一位
while (first < last && nums[first] === nums[++first]) { } // 如果相等就跳过
} else { // 实力太强,把大神那边右移一位
while (first < last && nums[last] === nums[--last]) { }
}
} while (first < last)
while (nums[i] === nums[++i]) { }
}
}
return res
}

9
src/math/add-binary.js Normal file
View File

@ -0,0 +1,9 @@
/**
* @param {string} a
* @param {string} b
* @return {string}
*/
export const addBinary = function (a, b) {
// eslint-disable-next-line no-undef
return (BigInt('0b' + a) + BigInt('0b' + b)).toString(2)
}

View File

@ -0,0 +1,52 @@
// 中位数:将一个集合划分为两个长度相等的子集,其中一个子集中的元素总是大于另一个子集中的元素。
// 参考https://leetcode-cn.com/problems/median-of-two-sorted-arrays/solution/xun-zhao-liang-ge-you-xu-shu-zu-de-zhong-wei-s-114/
/**
* @param {number[]} nums1
* @param {number[]} nums2
* @return {number}
*/
export const findMedianSortedArrays = function (nums1, nums2) {
if (nums1.length > nums2.length) return findMedianSortedArrays(nums2, nums1)
const m = nums1.length; const n = nums2.length
let left = 0; let right = m
let median1 = 0; let median2 = 0
while (left <= right) {
const i = (left + right) >> 1
const j = ((m + n + 1) >> 1) - i
const numsIm1 = (i === 0 ? Number.MIN_SAFE_INTEGER : nums1[i - 1]) // nums1[i-1]
const numsI = (i === m ? Number.MAX_SAFE_INTEGER : nums1[i]) // nums1[i]
const numsJm1 = (j === 0 ? Number.MIN_SAFE_INTEGER : nums2[j - 1]) // nums2[j-1]
const numsJ = (j === n ? Number.MAX_SAFE_INTEGER : nums2[j]) // nums2[j]
if (numsIm1 <= numsJ) {
median1 = Math.max(numsIm1, numsJm1)
median2 = Math.min(numsI, numsJ)
left = i + 1
} else {
right = i - 1
}
}
return (m + n) % 2 === 0 ? (median1 + median2) / 2.0 : median1
}
// 常规解法,不满足复杂度
// /**
// * @param {number[]} nums1
// * @param {number[]} nums2
// * @return {number}
// */
// var findMedianSortedArrays = function(nums1, nums2) {
// const newArr = nums1.concat(nums2).sort((a, b) => a - b)
// const length = newArr.length
// if (length % 2 === 0) {
// const half = length / 2
// return (newArr[half - 1] + newArr[half]) / 2
// } else {
// return newArr[(length - 1) / 2]
// }
// };

View File

@ -0,0 +1,16 @@
/**
* @param {number} x
* @return {boolean}
*/
export const isPalindrome = function (x) {
if (x < 0 || (x % 10 === 0 && x !== 0)) return false // 如果末尾数为0且不是0
let reverse = 0
while (reverse < x) {
reverse = reverse * 10 + x % 10
x = x / 10 | 0
}
return reverse === x || (reverse / 10 | 0) === x
}

View File

@ -0,0 +1,16 @@
const pn = (p) => { // 欧几里得-欧拉定理
return (1 << (p - 1)) * ((1 << p) - 1)
}
/**
* @param {number} num
* @return {boolean}
*/
export const checkPerfectNumber = function (num) {
const primes = [2, 3, 5, 7, 13, 17, 19, 31]
for (const prime of primes) {
if (pn(prime) === num) return true
}
return false
}

21
src/math/powx-n.js Normal file
View File

@ -0,0 +1,21 @@
/**
* @param {number} x
* @param {number} n
* @return {number}
*/
export const myPow = function (x, n) { // 参考:快速幂 + 迭代 https://leetcode-cn.com/problems/powx-n/solution/powx-n-by-leetcode-solution/
let ans = 1.0 // 答案
if (n < 0) { // 如果 n 为负
n = -n // 将 n 变为正
x = 1.0 / x // 2^-2 = 1/(2^2) = 1/4 = 0.25
}
while (n > 0) {
if (n & 1) ans *= x // 如果n的二进制最后一位为1则计入贡献
x *= x // 将贡献不断平方
n >>>= 1 // 无符号右移一位,相当于 n = n / 2 | 0 ,去掉二进制的最后一位,相当于下一次判断倒数第二位
}
return ans.toFixed(5)
}

View File

@ -0,0 +1,25 @@
/**
* @param {number[]} nums
* @param {number} k
* @return {number}
*/
export const subarraySum = function (nums, k) {
const map = new Map()
let sum = 0
let res = 0
nums.forEach((n, index) => {
sum += n
if (sum === k) res++
const subSum = sum - k
let value = []
if (map.has(subSum)) res += map.get(subSum).length
if (map.has(sum)) {
value = map.get(sum)
}
value.push(index)
map.set(sum, value)
})
return res
}

View File

@ -0,0 +1,36 @@
// s = "3[a]2[bc]", 返回 "aaabcbc".
// s = "3[a2[c]]", 返回 "accaccacc".
// s = "2[abc]3[cd]ef", 返回 "abcabccdcdcdef".
/**
* @param {string} s
* @return {string}
*/
export const decodeString = function (s) {
const stack = []
let multiple = ''
for (let i = 0, len = s.length; i < len; i++) {
if (!isNaN(Number(s[i]))) { // 判断是数字
if (i === 0 || !isNaN(Number(s[i - 1]))) { // 如果上一位也是数字,则
multiple += s[i]
} else {
multiple = s[i]
}
} else if (multiple && s[i] === '[') {
stack.push(Number(multiple))
multiple = ''
} else if (s[i] === ']') {
let current = stack.pop()
let tmpStr = ''
while (typeof current !== 'number') {
tmpStr = current + tmpStr
current = stack.pop()
}
tmpStr = tmpStr.repeat(current)
stack.push(tmpStr)
} else {
stack.push(s[i])
}
}
return stack.join('')
}

47
src/stack/min-stack.js Normal file
View File

@ -0,0 +1,47 @@
/**
* initialize your data structure here.
*/
export const MinStack = function () {
this.stack = []
this.minStack = [Infinity]
}
/**
* @param {number} x
* @return {void}
*/
MinStack.prototype.push = function (x) {
this.stack.push(x)
this.minStack.push(Math.min(this.minStack[this.minStack.length - 1], x))
}
/**
* @return {void}
*/
MinStack.prototype.pop = function () {
this.stack.pop()
this.minStack.pop()
}
/**
* @return {number}
*/
MinStack.prototype.top = function () {
return this.stack[this.stack.length - 1]
}
/**
* @return {number}
*/
MinStack.prototype.getMin = function () {
return this.minStack[this.minStack.length - 1]
}
/**
* Your MinStack object will be instantiated and called as such:
* var obj = new MinStack()
* obj.push(x)
* obj.pop()
* var param_3 = obj.top()
* var param_4 = obj.getMin()
*/

View File

@ -0,0 +1,37 @@
export var CQueue = function () {
this.stackA = []
this.stackB = []
}
/**
* @param {number} value
* @return {void}
*/
CQueue.prototype.appendTail = function (value) {
this.stackA.push(value)
}
/**
* @return {number}
*/
CQueue.prototype.deleteHead = function () {
const stackBNum = this.stackB.length
while (this.stackA.length) {
this.stackB.push(this.stackA.pop())
}
if (stackBNum !== 0) {
this.stackB.push(...this.stackB.splice(0, stackBNum))
}
const tmp = this.stackB.pop()
return tmp === undefined ? -1 : tmp
}
/**
* Your CQueue object will be instantiated and called as such:
* var obj = new CQueue()
* obj.appendTail(value)
* var param_2 = obj.deleteHead()
*/

View File

@ -0,0 +1,14 @@
/**
* @param {string} sentence
* @param {string} searchWord
* @return {number}
*/
export const isPrefixOfWord = function (sentence, searchWord) {
const items = sentence.split(' ')
for (const n in items) {
if (items[n].indexOf(searchWord) === 0) return Number(n) + 1
}
return -1
}

View File

@ -0,0 +1,7 @@
/**
* @param {string} address
* @return {string}
*/
export const defangIPaddr = function (address) {
return address.replace(/\./g, '[.]')
}

View File

@ -0,0 +1,30 @@
/**
* @param {string} s
* @return {number}
*/
export const findTheLongestSubstring = function (s) {
const n = s.length
const pos = new Array(1 << 5).fill(-1)
let ans = 0; let status = 0
pos[0] = 0
for (let i = 0; i < n; ++i) {
const ch = s.charAt(i)
if (ch === 'a') {
status ^= 1 << 0
} else if (ch === 'e') {
status ^= 1 << 1
} else if (ch === 'i') {
status ^= 1 << 2
} else if (ch === 'o') {
status ^= 1 << 3
} else if (ch === 'u') {
status ^= 1 << 4
}
if (~pos[status]) {
ans = Math.max(ans, i + 1 - pos[status])
} else {
pos[status] = i + 1
}
}
return ans
}

View File

@ -0,0 +1,19 @@
/**
* @param {number} num
* @return {string}
*/
export const intToRoman = function (num) {
const nums = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1]
const chars = ['M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I']
let result = ''
while (num) {
if (num >= nums[0]) { // 3 > 1 => 2 > 1 => 1 == 1
result += chars[0] // I => II => III
num -= nums[0] // 3 -> 2 => 2 -> 1 => 1 => 0
} else {
nums.shift()
chars.shift()
}
}
return result
}

View File

@ -0,0 +1,10 @@
/**
* @param {string} s
* @return {number}
*/
export const lengthOfLastWord = function (s) {
s = s.trim()
const tmp = s.lastIndexOf(' ')
const lastWord = s.substring(tmp === -1 ? 0 : tmp + 1, s.length)
return lastWord.length
}

View File

@ -0,0 +1,27 @@
const comp = (left, right, res) => {
if (left.length > right.length) {
[left, right] = [right, left]
}
res = res || left
while (right.indexOf(res) !== 0 && res.length > 0) {
res = res.slice(0, res.length - 1)
}
return res
}
/**
* @param {string[]} strs
* @return {string}
*/
export const longestCommonPrefix = function (strs) {
if (strs.length < 2) return strs[0] || ''
let res = strs[0]
for (let i = 1; i < strs.length; i++) {
res = comp(res, strs[i])
}
return res
}

View File

@ -0,0 +1,36 @@
export const longestPalindrome = function (s) {
if (!s || !s.trim()) return ''
if (s.length === 1) return s
if (s.length === 2) return s[0] === s[1] ? s[0] + s[1] : s[1]
let result = ''
/**
*扩散坐标
*/
const calPalindromeIndex = function (left, right, s) {
const len = s.length
while (left >= 0 && right < len && s[left] === s[right]) {
left--
right++
}
return { left: left + 1, right: right }
}
for (let i = 0, len = s.length; i < len; i++) {
let even = ''
let odd = ''
if (s[i] === s[i + 1]) {
// 经过当前位与下一位判断已构成回文,扩散位直接从下一位开始,可以提速
const evenIndex = calPalindromeIndex(i - 1, i + 2, s)
even = s.slice(evenIndex.left, evenIndex.right)
}
const oddIndex = calPalindromeIndex(i - 1, i + 1, s)
odd = s.slice(oddIndex.left, oddIndex.right)
const re = odd.length > even.length ? odd : even
result = result.length > re.length ? result : re
}
return result
}
// 作者liu-zi-qian-2
// 链接https://leetcode-cn.com/problems/longest-palindromic-substring/solution/5-zui-chang-hui-wen-zi-chuan-by-liu-zi-qian-2/
// 来源力扣LeetCode
// 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

View File

@ -0,0 +1,45 @@
const v = ['a', 'e', 'i', 'o', 'u']
const check = (str) => {
const map = new Map()
for (let i = 0; i < str.length; i++) {
if (v.includes(str[i])) {
map.set(str[i], (map.get(str[i]) || 0) + 1)
}
}
let res = 0
map.forEach(n => {
res += n
})
return res
}
/**
* @param {string} s
* @param {number} k
* @return {number}
*/
export const maxVowels = function (s, k) {
let i = 0
let res = 0
const temp = s.slice(i, i + k)
let tmp = check(temp)
res = Math.max(res, tmp)
while (i + k <= s.length) {
i++
if (v.includes(s[i + k - 1])) {
tmp++
}
if (v.includes(s[i - 1])) {
tmp--
}
res = Math.max(res, tmp)
}
return res
}

View File

@ -0,0 +1,40 @@
/**
* @param {string} s
* @param {string} t
* @return {string}
*/
export const minWindow = function (s, t) {
const sLen = s.length; const tLen = t.length
const tMap = new Map(); const map = new Map()
let l = 0; let r = 0; let res = ''
for (let i = 0; i < tLen; i++) {
tMap.set(t[i], (tMap.get(t[i]) || 0) + 1)
}
const check = (cMap) => {
const check = new Map(
[...cMap].filter(([k, v]) => tMap.has(k) && v >= tMap.get(k))
)
return check.size === tMap.size
}
while (r <= sLen) {
if (t.includes(s[r])) {
map.set(s[r], (map.get(s[r]) || 0) + 1)
}
while (check(map) && l <= r) {
const tmp = s.slice(l, r + 1)
if (res.length === 0 || tmp.length <= res.length) res = tmp
if (t.includes(s[l]) && map.has(s[l])) {
map.set(s[l], map.get(s[l]) - 1)
}
l++
}
r++
}
return res
}

View File

@ -0,0 +1,34 @@
/**
* @param {string} s
* @return {number}
*/
export const romanToInt = function (s) {
const map = new Map([
['I', 1],
['IV', 4],
['V', 5],
['IX', 9],
['X', 10],
['XL', 40],
['L', 50],
['XC', 90],
['C', 100],
['CD', 400],
['D', 500],
['CM', 900],
['M', 1000]
])
let ans = 0
let i = 0
while (i < s.length) {
if (i + 1 < s.length && map.has(s.substring(i, i + 2))) {
ans += map.get(s.substring(i, i + 2))
i += 2
} else {
ans += map.get(s.substring(i, i + 1))
i++
}
}
return ans
}

View File

@ -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
// }

View File

@ -0,0 +1,28 @@
/**
* Definition for a binary tree node.
* function TreeNode(val) {
* this.val = val;
* this.left = this.right = null;
* }
*/
/**
* @param {TreeNode} root
* @return {number[][]}
*/
export const levelOrder = function (root) {
const res = []
const queue = [root]
while (queue.length) { // BFS
const tmp = []
const leave = queue.length // 记录这一层有几个
for (let i = 0; i < leave; i++) { // 一次性把固定个数的队列执行完
const node = queue.shift()
if (node && node.left) queue.push(node.left)
if (node && node.right) queue.push(node.right)
if (node) tmp.push(node.val)
}
if (tmp.length) res.unshift(tmp)
}
return res
}

View File

@ -0,0 +1,28 @@
/**
* Definition for a binary tree node.
* function TreeNode(val) {
* this.val = val;
* this.left = this.right = null;
* }
*/
/**
* @param {TreeNode} root
* @return {number[][]}
*/
export const levelOrder = function (root) {
const res = []
const queue = [root]
while (queue.length) { // BFS
const tmp = []
const leave = queue.length // 记录这一层有几个
for (let i = 0; i < leave; i++) { // 一次性把固定个数的队列执行完
const node = queue.shift()
if (node && node.left) queue.push(node.left)
if (node && node.right) queue.push(node.right)
if (node) tmp.push(node.val)
}
if (tmp.length) res.push(tmp)
}
return res
}

View File

@ -0,0 +1,26 @@
/**
* Definition for a binary tree node.
*/
function TreeNode (val) {
this.val = val
this.left = this.right = null
}
// 前序遍历:根左右
// 中序遍历:左根右
// 前序遍历知道根、中序遍历知道左边长度。
/**
* @param {number[]} preorder
* @param {number[]} inorder
* @return {TreeNode}
*/
export const buildTree = function (preorder, inorder) {
if (inorder.length === 0) return null
const root = new TreeNode(preorder[0])
const index = inorder.indexOf(preorder[0])
root.left = buildTree(preorder.slice(1, index + 1), inorder.slice(0, index))
root.right = buildTree(preorder.slice(index + 1), inorder.slice(index + 1))
return root
}

View File

@ -0,0 +1,20 @@
import TreeNode from '../../test/tree/TreeNode'
/**
* @param {number[]} nums
* @return {TreeNode}
*/
export const sortedArrayToBST = function (nums) {
if (!nums.length) return null
const creatTree = (left, right) => {
if (left > right) return null
const mid = Math.floor((left + right) / 2)
const root = new TreeNode(nums[mid])
root.left = creatTree(left, mid - 1)
root.right = creatTree(mid + 1, right)
return root
}
return creatTree(0, nums.length - 1)
}

View File

@ -0,0 +1,20 @@
/**
* Definition for a binary tree node.
* function TreeNode(val) {
* this.val = val;
* this.left = this.right = null;
* }
*/
/**
* @param {TreeNode} root
* @param {TreeNode} p
* @param {TreeNode} q
* @return {TreeNode}
*/
export const lowestCommonAncestor = function (root, p, q) {
if (!root || root === p || root === q) return root
const left = lowestCommonAncestor(root.left, p, q)
const right = lowestCommonAncestor(root.right, p, q)
if ((left === p && right === q) || (left === q && right === p)) return root
return left || right
}

View File

@ -0,0 +1,12 @@
// 卡塔兰数
/**
* @param {number} n
* @return {number}
*/
export const numTrees = function (n) {
let C = 1
for (let i = 0; i < n; ++i) {
C = C * 2 * (2 * i + 1) / (i + 2)
}
return C
}

View File

@ -0,0 +1,5 @@
import { dailyTemperatures } from '../../src/array/daily-temperatures.js'
test('每日温度', () => {
expect(dailyTemperatures([73, 74, 75, 71, 69, 72, 76, 73])).toEqual([1, 1, 4, 2, 1, 1, 0, 0])
})

View File

@ -0,0 +1,6 @@
import { findDuplicate } from '../../src/array/find-the-duplicate-number'
test('寻找重复数', () => {
expect(findDuplicate([1, 3, 4, 2, 2])).toBe(2)
expect(findDuplicate([3, 1, 3, 4, 2])).toBe(3)
})

View File

@ -0,0 +1,5 @@
import { firstUniqChar } from '../../src/array/first-unique-character-in-a-string'
test('第一个只出现一次的字符', () => {
expect(firstUniqChar('leetcode')).toBe('l')
})

View File

@ -0,0 +1,7 @@
import { firstUniqueNumber } from '../../src/array/first-unique-number-in-data-stream'
test('数据流中第一个唯一的数字', () => {
expect(firstUniqueNumber([1, 2, 2, 1, 3, 4, 4, 5, 6], 5)).toBe(3)
expect(firstUniqueNumber([1, 2, 2, 1, 3, 4, 4, 5, 6], 7)).toBe(-1)
expect(firstUniqueNumber([1, 2, 2, 1, 3, 4], 3)).toBe(3)
})

View File

@ -0,0 +1,6 @@
import { highestFrequency } from '../../src/array/highest-frequency-ip'
test('最高频率的IP', () => {
expect(highestFrequency(['192.168.1.1', '192.118.2.1', '192.168.1.1'])).toEqual('192.168.1.1')
expect(highestFrequency(['192.168.1.1', '192.118.2.1', '192.168.1.1', '192.118.2.1', '192.118.2.1'])).toEqual('192.118.2.1')
})

View File

@ -0,0 +1,7 @@
import { rob } from '../../src/array/house-robber'
test('打家劫舍', () => {
expect(rob([1, 2, 3, 1])).toBe(4)
expect(rob([2, 7, 9, 3, 1])).toBe(12)
expect(rob([828, 125, 740, 724, 983, 321, 773, 678, 841, 842, 875, 377, 674, 144, 340, 467, 625, 916, 463, 922, 255, 662, 692, 123, 778, 766, 254, 559, 480, 483, 904, 60, 305, 966, 872, 935, 626, 691, 832, 998, 508, 657, 215, 162, 858, 179, 869, 674, 452, 158, 520, 138, 847, 452, 764, 995, 600, 568, 92, 496, 533, 404, 186, 345, 304, 420, 181, 73, 547, 281, 374, 376, 454, 438, 553, 929, 140, 298, 451, 674, 91, 531, 685, 862, 446, 262, 477, 573, 627, 624, 814, 103, 294, 388])).toBe(29123)
})

View File

@ -0,0 +1,7 @@
import { kidsWithCandies } from '../../src/array/kids-with-the-greatest-number-of-candies'
test('拥有最多糖果的孩子', () => {
expect(kidsWithCandies([2, 3, 5, 1, 3], 3)).toEqual([true, true, true, false, true])
expect(kidsWithCandies([4, 2, 1, 1, 2], 1)).toEqual([true, false, false, false, false])
expect(kidsWithCandies([12, 1, 12], 10)).toEqual([true, false, true])
})

View File

@ -0,0 +1,20 @@
import { kthSmallest } from '../../src/array/kth-smallest-element-in-a-sorted-matrix.js'
test('有序矩阵中第K小的元素', () => {
expect(kthSmallest([
[1, 5, 9],
[10, 11, 13],
[12, 13, 15]
], 8)).toBe(13)
expect(kthSmallest([
[1, 5, 7],
[3, 7, 8],
[4, 8, 9]
], 4)).toBe(5)
expect(kthSmallest([
[1, 2],
[3, 4]
], 3)).toBe(3)
})

View File

@ -0,0 +1,9 @@
import { lemonadeChange } from '../../src/array/lemonade-change'
test('柠檬水找零', () => {
expect(lemonadeChange([5, 5, 5, 5, 10, 5, 10, 10, 10, 20])).toBe(true)
expect(lemonadeChange([5, 5, 5, 10, 20])).toBe(true)
expect(lemonadeChange([5, 5, 10])).toBe(true)
expect(lemonadeChange([10, 10])).toBe(false)
expect(lemonadeChange([5, 5, 10, 10, 20])).toBe(false)
})

View File

@ -0,0 +1,15 @@
import LRUCache from '../../src/array/lru-cache'
test('LRU缓存机制', () => {
const cache = new LRUCache(2 /* 缓存容量 */)
cache.put(1, 1)
cache.put(2, 2)
expect(cache.get(1)).toBe(1) // 返回 1
cache.put(3, 3) // 该操作会使得密钥 2 作废
expect(cache.get(2)).toBe(-1) // 返回 -1 (未找到)
cache.put(4, 4) // 该操作会使得密钥 1 作废
expect(cache.get(1)).toBe(-1) // 返回 -1 (未找到)
expect(cache.get(3)).toBe(3) // 返回 3
expect(cache.get(4)).toBe(4) // 返回 4
})

View File

@ -0,0 +1,5 @@
import { findLength } from '../../src/array/maximum-length-of-repeated-subarray.js'
test('最长重复子数组', () => {
expect(findLength([1, 2, 3, 2, 1], [3, 2, 1, 4, 7])).toBe(3)
})

View File

@ -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)
})

View File

@ -0,0 +1,5 @@
import { productExceptSelf } from '../../src/array/product-of-array-except-self'
test('除自身以外数组的乘积', () => {
expect(productExceptSelf([1, 2, 3, 4])).toEqual([24, 12, 8, 6])
})

View File

@ -0,0 +1,5 @@
import { subarraysDivByK } from '../../src/array/subarray-sums-divisible-by-k'
test('和可被K整除的子数组', () => {
expect(subarraysDivByK([4, 5, 0, -2, -3, 1], 5)).toBe(7)
})

View File

@ -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])
})

27
test/list/ListNode.js Normal file
View File

@ -0,0 +1,27 @@
export default class ListNode {
constructor (val) {
this.val = val
this.next = null
}
}
export const arrToList = (arr) => {
const head = new ListNode(arr[0])
let current = head
for (let n = 1, len = arr.length; n < len; n++) {
current.next = new ListNode(arr[n])
current = current.next
}
return head
}
export const listToArr = (list) => {
const arr = []
while (list) {
arr.push(list.val)
list = list.next
}
return arr
}

View File

@ -1,20 +1,5 @@
import { hasCycle } from '../../src/list/linked-list-cycle' import { hasCycle } from '../../src/list/linked-list-cycle'
import { arrToList } from './ListNode'
function ListNode (val) {
this.val = val
this.next = null
}
const arrToList = (arr) => {
const head = new ListNode(arr[0])
let current = head
for (let n = 1, len = arr.length; n < len; n++) {
current.next = new ListNode(arr[n])
current = current.next
}
return head
}
test('环形链表', () => { test('环形链表', () => {
const list = arrToList([1, 2, 3]) const list = arrToList([1, 2, 3])

View File

@ -1,62 +1,45 @@
import { merge, mergeKLists } from '../../src/list/merge-k-sorted-lists' import { merge, mergeKLists } from '../../src/list/merge-k-sorted-lists'
import { arrToList } from './ListNode'
function ListNode (val) {
this.val = val
this.next = null
}
const arr2List = (arr) => {
let first = null
let res = null
for (let n = 0, len = arr.length; n < len; n++) {
const tmp = new ListNode(arr[n])
if (res) res.next = tmp
else first = tmp
res = tmp
}
return first
}
test('数组转链表', () => { test('数组转链表', () => {
expect(arr2List([1, 2, 3])).toEqual({ next: { next: { next: null, val: 3 }, val: 2 }, val: 1 }) expect(arrToList([1, 2, 3])).toEqual({ next: { next: { next: null, val: 3 }, val: 2 }, val: 1 })
}) })
test('合并俩链表', () => { test('合并俩链表', () => {
const source1 = arr2List([1, 4, 5]) const source1 = arrToList([1, 4, 5])
const source2 = arr2List([1, 3, 4]) const source2 = arrToList([1, 3, 4])
const out = [1, 1, 3, 4, 4, 5] const out = [1, 1, 3, 4, 4, 5]
expect(merge(source1, source2)).toEqual(arr2List(out)) expect(merge(source1, source2)).toEqual(arrToList(out))
}) })
test('合并K个排序链表 - 1', () => { test('合并K个排序链表 - 1', () => {
const source = [ const source = [
arr2List([1, 4, 5]), arrToList([1, 4, 5]),
arr2List([1, 3, 4]), arrToList([1, 3, 4]),
arr2List([2, 6]) arrToList([2, 6])
] ]
const out = [1, 1, 2, 3, 4, 4, 5, 6] const out = [1, 1, 2, 3, 4, 4, 5, 6]
expect(mergeKLists(source)).toEqual(arr2List(out)) expect(mergeKLists(source)).toEqual(arrToList(out))
}) })
test('合并K个排序链表 - 2', () => { test('合并K个排序链表 - 2', () => {
const source = [ const source = [
arr2List([2, 4, null]), arrToList([2, 4, null]),
arr2List([null]), arrToList([null]),
arr2List([-1, null]) arrToList([-1, null])
] ]
const out = [-1, 2, 4, null] const out = [-1, 2, 4, null]
expect(mergeKLists(source)).toEqual(arr2List(out)) expect(mergeKLists(source)).toEqual(arrToList(out))
}) })
test('合并K个排序链表 - 3', () => { test('合并K个排序链表 - 3', () => {
const source = [ const source = [
arr2List([2, 6, null]), arrToList([2, 6, null]),
arr2List([5, null]), arrToList([5, null]),
arr2List([7, null]) arrToList([7, null])
] ]
const out = [2, 5, 6, 7, null] const out = [2, 5, 6, 7, null]
expect(mergeKLists(source)).toEqual(arr2List(out)) expect(mergeKLists(source)).toEqual(arrToList(out))
}) })

View File

@ -1,20 +1,5 @@
import { mergeTwoLists } from '../../src/list/merge-two-sorted-lists' import { mergeTwoLists } from '../../src/list/merge-two-sorted-lists'
import { arrToList } from './ListNode'
function ListNode (val) {
this.val = val
this.next = null
}
const arrToList = (arr) => {
const head = new ListNode(arr[0])
let current = head
for (let n = 1, len = arr.length; n < len; n++) {
current.next = new ListNode(arr[n])
current = current.next
}
return head
}
test('合并两个有序链表', () => { test('合并两个有序链表', () => {
expect(mergeTwoLists(arrToList([1, 2, 4]), arrToList([1, 3, 4]))).toEqual(arrToList([1, 1, 2, 3, 4, 4])) expect(mergeTwoLists(arrToList([1, 2, 4]), arrToList([1, 3, 4]))).toEqual(arrToList([1, 1, 2, 3, 4, 4]))

View File

@ -0,0 +1,9 @@
import { middleNode } from '../../src/list/middle-of-the-linked-list'
import { arrToList } from './ListNode'
test('链表的中间节点', () => {
expect(middleNode(arrToList([1]))).toEqual(arrToList([1]))
expect(middleNode(arrToList([1, 2]))).toEqual(arrToList([2]))
expect(middleNode(arrToList([1, 2, 3, 4, 5]))).toEqual(arrToList([3, 4, 5]))
expect(middleNode(arrToList([1, 2, 3, 4, 5, 6]))).toEqual(arrToList([4, 5, 6]))
})

View File

@ -0,0 +1,11 @@
import { reverseKGroup } from '../../src/list/reverse-nodes-in-k-group'
import { arrToList, listToArr } from './ListNode'
test('K个一组翻转链表', () => {
const res = reverseKGroup(arrToList([1, 2, 3, 4, 5]), 3)
expect(listToArr(res)).toEqual([3, 2, 1, 4, 5])
expect(res).toEqual(arrToList([3, 2, 1, 4, 5]))
expect(reverseKGroup(arrToList([1, 2, 3, 4, 5]), 2)).toEqual(arrToList([2, 1, 4, 3, 5]))
expect(reverseKGroup(arrToList([1, 2, 3, 4, 5, 6]), 2)).toEqual(arrToList([2, 1, 4, 3, 6, 5]))
expect(reverseKGroup(arrToList([1, 2, 3, 4, 5, 6, 7, 8]), 2)).toEqual(arrToList([2, 1, 4, 3, 6, 5, 8, 7]))
})

View File

@ -1,20 +1,5 @@
import { sortList } from '../../src/list/sort-list' import { sortList } from '../../src/list/sort-list'
import { arrToList } from './ListNode'
function ListNode (val) {
this.val = val
this.next = null
}
const arrToList = (arr) => {
const head = new ListNode(arr[0])
let current = head
for (let n = 1, len = arr.length; n < len; n++) {
current.next = new ListNode(arr[n])
current = current.next
}
return head
}
test('链表排序', () => { test('链表排序', () => {
const source = [4, 2, 1, 3] const source = [4, 2, 1, 3]

8
test/math/3sum.test.js Normal file
View File

@ -0,0 +1,8 @@
import { threeSum } from '../../src/math/3sum.js'
test('三数之和', () => {
expect(threeSum([-1, 0, 1, 2, -1, -4])).toEqual([
[-1, -1, 2],
[-1, 0, 1]
])
})

View File

@ -0,0 +1,6 @@
import { addBinary } from '../../src/math/add-binary'
test('二进制求和', () => {
expect(addBinary('11', '1')).toEqual('100')
expect(addBinary('1010', '1011')).toEqual('10101')
})

View File

@ -0,0 +1,7 @@
import { findMedianSortedArrays } from '../../src/math/median-of-two-sorted-arrays'
test('寻找两个正序数组的中位数', () => {
expect(findMedianSortedArrays([], [1])).toBe(1.0)
expect(findMedianSortedArrays([1, 3], [2])).toBe(2.0)
expect(findMedianSortedArrays([1, 2], [3, 4])).toBe(2.5)
})

View File

@ -0,0 +1,9 @@
import { isPalindrome } from '../../src/math/palindrome-number'
test('回文数', () => {
expect(isPalindrome(121)).toBe(true)
expect(isPalindrome(0)).toBe(true)
expect(isPalindrome(11)).toBe(true)
expect(isPalindrome(10)).toBe(false)
expect(isPalindrome(-121)).toBe(false)
})

View File

@ -0,0 +1,6 @@
import { checkPerfectNumber } from '../../src/math/perfect-number'
test('完美数', () => {
expect(checkPerfectNumber(28)).toBe(true)
expect(checkPerfectNumber(2)).toBe(false)
})

7
test/math/powx-n.test.js Normal file
View File

@ -0,0 +1,7 @@
import { myPow } from '../../src/math/powx-n'
test('Pow(x, n)', () => {
expect(myPow(2.00000, 10)).toBe('1024.00000')
expect(myPow(2.10000, 3)).toBe('9.26100')
expect(myPow(2.00000, -2)).toBe('0.25000')
})

View File

@ -0,0 +1,5 @@
import { subarraySum } from '../../src/math/subarray-sum-equals-k'
test('和为K的子数组', () => {
expect(subarraySum([1, 1, 1], 2)).toBe(2)
})

View File

@ -0,0 +1,7 @@
import { decodeString } from '../../src/stack/decode-string'
test('字符串解码', () => {
expect(decodeString('3[a]2[bc]')).toBe('aaabcbc')
expect(decodeString('3[a2[c]]')).toBe('accaccacc')
expect(decodeString('2[abc]3[cd]ef')).toBe('abcabccdcdcdef')
})

View File

@ -0,0 +1,13 @@
import { MinStack } from '../../src/stack/min-stack'
test('最小栈', () => {
var obj = new MinStack()
obj.push(1)
obj.push(3)
obj.push(2)
obj.pop()
var top = obj.top()
var min = obj.getMin()
expect(top).toBe(3)
expect(min).toBe(1)
})

View File

@ -0,0 +1,67 @@
import { CQueue } from '../../src/stack/yong-liang-ge-zhan-shi-xian-dui-lie-lcof.js'
test('用两个栈实现队列 - 1', () => {
let obj = null
const action = ['CQueue', 'appendTail', 'deleteHead', 'deleteHead']
const queue = [[], [3], [], []]
const res = []
while (queue.length) {
const tmp = action.shift()
const val = queue.shift()
if (tmp === 'CQueue') {
obj = new CQueue()
res.push(null)
} else if (tmp === 'appendTail') {
obj.appendTail(val[0])
res.push(null)
} else if (tmp === 'deleteHead') {
res.push(obj.deleteHead())
}
}
expect(res).toEqual([null, null, 3, -1])
})
test('用两个栈实现队列 - 2', () => {
let obj = null
const action = ['CQueue', 'deleteHead', 'appendTail', 'appendTail', 'deleteHead', 'deleteHead']
const queue = [[], [], [5], [2], [], []]
const res = []
while (queue.length) {
const tmp = action.shift()
const val = queue.shift()
if (tmp === 'CQueue') {
obj = new CQueue()
res.push(null)
} else if (tmp === 'appendTail') {
obj.appendTail(val[0])
res.push(null)
} else if (tmp === 'deleteHead') {
res.push(obj.deleteHead())
}
}
expect(res).toEqual([null, -1, null, null, 5, 2])
})
test('用两个栈实现队列 - 3', () => {
let obj = null
const action = ['CQueue', 'deleteHead', 'appendTail', 'deleteHead', 'deleteHead', 'deleteHead', 'deleteHead', 'appendTail', 'deleteHead', 'appendTail', 'appendTail', 'deleteHead', 'deleteHead', 'deleteHead', 'appendTail', 'deleteHead', 'deleteHead', 'deleteHead', 'deleteHead', 'appendTail', 'appendTail', 'appendTail', 'appendTail', 'deleteHead', 'deleteHead', 'appendTail', 'appendTail', 'deleteHead', 'deleteHead', 'deleteHead', 'appendTail', 'appendTail', 'deleteHead', 'appendTail', 'deleteHead', 'appendTail', 'appendTail', 'appendTail', 'deleteHead', 'deleteHead', 'appendTail', 'appendTail', 'deleteHead', 'deleteHead', 'deleteHead', 'deleteHead', 'appendTail', 'appendTail', 'deleteHead', 'deleteHead', 'appendTail', 'deleteHead', 'appendTail', 'appendTail', 'appendTail', 'appendTail', 'deleteHead', 'appendTail', 'deleteHead', 'deleteHead', 'appendTail', 'appendTail', 'appendTail', 'deleteHead', 'deleteHead', 'appendTail', 'appendTail', 'appendTail', 'deleteHead', 'deleteHead', 'deleteHead', 'deleteHead', 'appendTail', 'appendTail', 'deleteHead', 'deleteHead', 'appendTail', 'deleteHead', 'appendTail', 'appendTail', 'deleteHead', 'deleteHead', 'appendTail', 'deleteHead', 'appendTail', 'appendTail', 'appendTail', 'deleteHead', 'appendTail', 'appendTail', 'appendTail', 'appendTail', 'deleteHead', 'deleteHead', 'deleteHead', 'appendTail', 'deleteHead', 'appendTail', 'deleteHead', 'appendTail', 'appendTail']
const queue = [[], [], [97], [], [], [], [], [15], [], [1], [43], [], [], [], [18], [], [], [], [], [36], [69], [21], [91], [], [], [22], [40], [], [], [], [81], [65], [], [77], [], [63], [96], [5], [], [], [35], [90], [], [], [], [], [77], [83], [], [], [52], [], [2], [66], [87], [90], [], [2], [], [], [33], [16], [72], [], [], [14], [78], [8], [], [], [], [], [3], [83], [], [], [13], [], [79], [44], [], [], [33], [], [55], [76], [12], [], [91], [24], [49], [47], [], [], [], [85], [], [69], [], [94], [52]]
const res = []
while (queue.length) {
const tmp = action.shift()
const val = queue.shift()
if (tmp === 'CQueue') {
obj = new CQueue()
res.push(null)
} else if (tmp === 'appendTail') {
obj.appendTail(val[0])
res.push(null)
} else if (tmp === 'deleteHead') {
res.push(obj.deleteHead())
}
}
expect(res).toEqual([null, -1, null, 97, -1, -1, -1, null, 15, null, null, 1, 43, -1, null, 18, -1, -1, -1, null, null, null, null, 36, 69, null, null, 21, 91, 22, null, null, 40, null, 81, null, null, null, 65, 77, null, null, 63, 96, 5, 35, null, null, 90, 77, null, 83, null, null, null, null, 52, null, 2, 66, null, null, null, 87, 90, null, null, null, 2, 33, 16, 72, null, null, 14, 78, null, 8, null, null, 3, 83, null, 13, null, null, null, 79, null, null, null, null, 44, 33, 55, null, 76, null, 12, null, null])
})

View File

@ -0,0 +1,5 @@
import { isPrefixOfWord } from '../../src/string/check-if-a-word-occurs-as-a-prefix-of-any-word-in-a-sentence'
test('检查单词是否为句中其他单词的前缀', () => {
expect(isPrefixOfWord('i love eating burger', 'burg')).toBe(4)
})

View File

@ -0,0 +1,6 @@
import { defangIPaddr } from '../../src/string/defanging-an-ip-address'
test('IP地址无效化', () => {
expect(defangIPaddr('1.1.1.1')).toBe('1[.]1[.]1[.]1')
expect(defangIPaddr('255.100.50.0')).toBe('255[.]100[.]50[.]0')
})

View File

@ -0,0 +1,7 @@
import { findTheLongestSubstring } from '../../src/string/find-the-longest-substring-containing-vowels-in-even-counts'
test('每个元音包含偶数次的最长子字符串', () => {
expect(findTheLongestSubstring('eleetminicoworoep')).toBe(13)
expect(findTheLongestSubstring('leetcodeisgreat')).toBe(5)
expect(findTheLongestSubstring('bcbcbc')).toBe(6)
})

View File

@ -0,0 +1,9 @@
import { intToRoman } from '../../src/string/integer-to-roman'
test('整数转罗马数字', () => {
expect(intToRoman(2)).toBe('II')
expect(intToRoman(3)).toBe('III')
expect(intToRoman(4)).toBe('IV')
expect(intToRoman(9)).toBe('IX')
expect(intToRoman(58)).toBe('LVIII')
})

View File

@ -0,0 +1,5 @@
import { lengthOfLastWord } from '../../src/string/length-of-last-word'
test('最后一个单词的长度', () => {
expect(lengthOfLastWord('b a ')).toBe(1)
})

View File

@ -0,0 +1,8 @@
import { longestCommonPrefix } from '../../src/string/longest-common-prefix'
test('最长公共前缀', () => {
expect(longestCommonPrefix(['flower', 'flow', 'flight'])).toBe('fl')
expect(longestCommonPrefix(['dog', 'racecar', 'car'])).toBe('')
expect(longestCommonPrefix(['a'])).toBe('a')
expect(longestCommonPrefix(['caa', '', 'a', 'acb'])).toBe('')
})

View File

@ -0,0 +1,6 @@
import { longestPalindrome } from '../../src/string/longest-palindromic-substring'
test('最长回文字符串', () => {
expect(longestPalindrome('babad')).toBe('aba') // bab也是有效答案
expect(longestPalindrome('cbbd')).toBe('bb')
})

View File

@ -0,0 +1,6 @@
import { maxVowels } from '../../src/string/maximum-number-of-vowels-in-a-substring-of-given-length'
test('定长子串中元音的最大数目', () => {
expect(maxVowels('abciiidef', 3)).toBe(3)
expect(maxVowels('rhythms', 4)).toBe(0)
})

View File

@ -0,0 +1,9 @@
import { minWindow } from '../../src/string/minimum-window-substring'
test('最小覆盖子串', () => {
expect(minWindow('ab', 'a')).toBe('a')
expect(minWindow('ADOBECODEBANC', 'ABC')).toBe('BANC')
expect(minWindow('a', 'a')).toBe('a')
expect(minWindow('a', 'aa')).toBe('')
expect(minWindow('abcdc', 'da')).toBe('abcd')
})

View File

@ -0,0 +1,8 @@
import { romanToInt } from '../../src/string/roman-to-integer'
test('罗马数字转整数', () => {
expect(romanToInt('III')).toBe(3)
expect(romanToInt('IV')).toBe(4)
expect(romanToInt('IX')).toBe(9)
expect(romanToInt('LVIII')).toBe(58)
})

View File

@ -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)
})

View File

@ -0,0 +1,14 @@
import { levelOrder } from '../../src/tree/binary-tree-level-order-traversal-ii'
import Tree from './Tree.js'
test('二叉树的层序遍历 II', () => {
const source = [3, 9, 20, null, null, 15, 7]
expect(levelOrder(Tree.arrToTree(source))).toEqual([
[15, 7],
[9, 20],
[3]
])
const source1 = []
expect(levelOrder(Tree.arrToTree(source1))).toEqual([])
})

View File

@ -0,0 +1,14 @@
import { levelOrder } from '../../src/tree/binary-tree-level-order-traversal'
import Tree from './Tree.js'
test('二叉树的层序遍历', () => {
const source = [3, 9, 20, null, null, 15, 7]
expect(levelOrder(Tree.arrToTree(source))).toEqual([
[3],
[9, 20],
[15, 7]
])
const source1 = []
expect(levelOrder(Tree.arrToTree(source1))).toEqual([])
})

View File

@ -0,0 +1,5 @@
import { buildTree } from '../../src/tree/construct-binary-tree-from-preorder-and-inorder-traversal'
test('从前序与中序遍历序列构造二叉树', () => {
expect(buildTree([3, 9, 20, 15, 7], [9, 3, 15, 20, 7])).toEqual({ left: { left: null, right: null, val: 9 }, right: { left: { left: null, right: null, val: 15 }, right: { left: null, right: null, val: 7 }, val: 20 }, val: 3 })
})

View File

@ -0,0 +1,5 @@
import { sortedArrayToBST } from '../../src/tree/convert-sorted-array-to-binary-search-tree.js'
test('将有序数组转换为二叉搜索树', () => {
expect(sortedArrayToBST([-10, -3, 0, 5, 9])).toEqual({ left: { left: null, right: { left: null, right: null, val: -3 }, val: -10 }, right: { left: null, right: { left: null, right: null, val: 9 }, val: 5 }, val: 0 })
})

View File

@ -0,0 +1,8 @@
import { lowestCommonAncestor } from '../../src/tree/lowest-common-ancestor-of-a-binary-tree'
import Tree from './Tree'
test('二叉树的最近公共祖先', () => {
const head = Tree.arrToTree([3, 5, 1, 6, 2, 0, 8, null, null, 7, 4])
expect(lowestCommonAncestor(head, head.left, head.right)).toEqual(head)
expect(lowestCommonAncestor(head, head.left, head.left.right.right)).toEqual(head.left)
})

View File

@ -0,0 +1,5 @@
import { numTrees } from '../../src/tree/unique-binary-search-trees'
test('不同的二叉搜索树', () => {
expect(numTrees(3)).toBe(5)
})