add: 二叉树的最近公共祖先
This commit is contained in:
commit
da0e4f1359
10
.vscode/settings.json
vendored
10
.vscode/settings.json
vendored
@ -1,10 +1,18 @@
|
||||
{
|
||||
"cSpell.words": [
|
||||
"abcdefg",
|
||||
"cdefgab",
|
||||
"chuan",
|
||||
"dvdf",
|
||||
"lcci",
|
||||
"lcof",
|
||||
"lrloseumgh",
|
||||
"mincost",
|
||||
"nums",
|
||||
"pwwkew",
|
||||
"zhong"
|
||||
"umghlrlose",
|
||||
"xuan",
|
||||
"zhong",
|
||||
"zhuan"
|
||||
]
|
||||
}
|
26
README.md
26
README.md
@ -67,6 +67,10 @@ LeetCode 与 LintCode 解题记录。此为个人练习仓库,代码中对重
|
||||
|
||||
- 面试题参考思路,不严谨实现 廖雪峰 不要使用JavaScript内置的parseInt()函数,利用map和reduce操作实现一个string2int()函数。 https://www.liaoxuefeng.com/wiki/1022910821149312/1024322552460832
|
||||
|
||||
- [左旋转字符串](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/
|
||||
|
||||
## 数组
|
||||
|
||||
- [电话号码的字母组合](src/array/letter-combinations-of-a-phone-number.js)
|
||||
@ -253,7 +257,16 @@ LeetCode 与 LintCode 解题记录。此为个人练习仓库,代码中对重
|
||||
|
||||
- [最大数和最小数](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)
|
||||
|
||||
- LeetCode 983. 最低票价 https://leetcode-cn.com/problems/minimum-cost-for-tickets/
|
||||
|
||||
- [最大正方形](src/array/maximal-square.js)
|
||||
|
||||
- LeetCode 221. 最大正方形 https://leetcode-cn.com/problems/maximal-square/
|
||||
- LintCode 436. 最大正方形 https://www.lintcode.com/problem/maximal-square/description
|
||||
|
||||
## 栈
|
||||
|
||||
@ -310,6 +323,11 @@ LeetCode 与 LintCode 解题记录。此为个人练习仓库,代码中对重
|
||||
- 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)
|
||||
|
||||
- LeetCode 572. 另一个树的子树 https://leetcode-cn.com/problems/subtree-of-another-tree/
|
||||
- LintCode 1165. 另一个树的子树 https://www.lintcode.com/problem/subtree-of-another-tree/description
|
||||
|
||||
## 链表
|
||||
|
||||
- [合并K个排序链表](src/list/merge-k-sorted-lists.js)
|
||||
@ -320,9 +338,15 @@ LeetCode 与 LintCode 解题记录。此为个人练习仓库,代码中对重
|
||||
- [合并两个有序链表](src/list/merge-two-sorted-lists.js)
|
||||
|
||||
- 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
|
||||
- LintCode 165. 合并两个排序链表 https://www.lintcode.com/problem/merge-two-sorted-lists/description
|
||||
|
||||
- [链表排序](src/list/sort-list.js)
|
||||
|
||||
- LeetCode 148. 排序链表 https://leetcode-cn.com/problems/sort-list/
|
||||
- LintCode 98. 链表排序 https://www.lintcode.com/problem/sort-list/description
|
||||
|
||||
- [环形链表](src/list/linked-list-cycle.js)
|
||||
|
||||
- LeetCode 141. 环形链表 https://leetcode-cn.com/problems/linked-list-cycle/
|
||||
- LintCode 102. 带环链表 https://www.lintcode.com/problem/linked-list-cycle/description
|
||||
|
25
src/array/maximal-square.js
Normal file
25
src/array/maximal-square.js
Normal file
@ -0,0 +1,25 @@
|
||||
/**
|
||||
* @param {character[][]} matrix
|
||||
* @return {number}
|
||||
*/
|
||||
export const maximalSquare = function (matrix) {
|
||||
if (!matrix || !matrix[0]) return 0
|
||||
|
||||
const rows = matrix.length
|
||||
const cols = matrix[0].length
|
||||
let max = 0
|
||||
|
||||
const dp = new Array(rows).fill().map(_ => new Array(cols).fill(0))
|
||||
|
||||
for (let n = 0; n < rows; n++) {
|
||||
for (let i = 0; i < cols; i++) {
|
||||
if (Number(matrix[n][i]) === 1) {
|
||||
if (n === 0 || i === 0) dp[n][i] = 1
|
||||
else dp[n][i] = Math.min(dp[n - 1][i], dp[n][i - 1], dp[n - 1][i - 1]) + 1 // 找规律
|
||||
max = Math.max(max, dp[n][i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return max * max
|
||||
}
|
43
src/array/minimum-cost-for-tickets.js
Normal file
43
src/array/minimum-cost-for-tickets.js
Normal file
@ -0,0 +1,43 @@
|
||||
/**
|
||||
* @param {number[]} days
|
||||
* @param {number[]} costs
|
||||
* @return {number}
|
||||
*/
|
||||
export const mincostTickets = function (days, costs) {
|
||||
// 动态规划:
|
||||
// dp[i]: 从第i天开始,到最后一天所用的票价总和
|
||||
|
||||
// 思路:
|
||||
// 1. 记录数组中的最早的一天和最后的一天,动态规划从最后一天向前到最早一天即可,因为
|
||||
// 其他时间不需要消耗通行证
|
||||
// 2. 用一个变量 k 指针从 days 的最后一个索引向前走,i 指针也从最后一天向前走,但是遇到了
|
||||
// 不需要花费通行证的某些天走 else 分支即可,即后一天的总花费就是这一天的总花费
|
||||
// 3. 如果遇到需要通行证的时候,分别对比买一天、七天、三十天、所需的总花费,选择总花费最少的策略即可
|
||||
// 4. 初始化的时候 dp 数组多了 30,是为了简化有的用例第 365 天需要出行,选择买 30 天
|
||||
// 通行证的时候的特判
|
||||
|
||||
// 作者:ignore_express
|
||||
// 链接:https://leetcode-cn.com/problems/minimum-cost-for-tickets/solution/js-dong-tai-gui-hua-si-lu-jiang-jie-by-ignore_expr/
|
||||
// 来源:力扣(LeetCode)
|
||||
// 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
|
||||
const dp = new Array(366 + 30).fill(0)
|
||||
const n = days.length
|
||||
const maxDay = days[n - 1]
|
||||
const minDay = days[0]
|
||||
let k = n - 1
|
||||
|
||||
for (let i = maxDay; i >= minDay; i--) {
|
||||
if (i === days[k]) {
|
||||
dp[i] = Math.min(
|
||||
dp[i + 1] + costs[0],
|
||||
dp[i + 7] + costs[1],
|
||||
dp[i + 30] + costs[2]
|
||||
)
|
||||
k--
|
||||
} else {
|
||||
dp[i] = dp[i + 1]
|
||||
}
|
||||
}
|
||||
|
||||
return dp[minDay]
|
||||
}
|
28
src/list/linked-list-cycle.js
Normal file
28
src/list/linked-list-cycle.js
Normal file
@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Definition for singly-linked list.
|
||||
* function ListNode(val) {
|
||||
* this.val = val;
|
||||
* this.next = null;
|
||||
* }
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {ListNode} head
|
||||
* @return {boolean}
|
||||
*/
|
||||
export const hasCycle = function (head) {
|
||||
if (!head || !head.next) return false
|
||||
|
||||
// 双指针解法
|
||||
let slow = head
|
||||
let fast = head.next
|
||||
|
||||
while (true) {
|
||||
if (!fast || !fast.next) return false
|
||||
else if (fast.next === slow || fast === slow) return true
|
||||
else {
|
||||
fast = fast.next.next
|
||||
slow = slow.next
|
||||
}
|
||||
}
|
||||
}
|
8
src/string/zuo-xuan-zhuan-zi-fu-chuan-lcof.js
Normal file
8
src/string/zuo-xuan-zhuan-zi-fu-chuan-lcof.js
Normal file
@ -0,0 +1,8 @@
|
||||
/**
|
||||
* @param {string} s
|
||||
* @param {number} n
|
||||
* @return {string}
|
||||
*/
|
||||
export const reverseLeftWords = function (s, n) {
|
||||
return (s + s).substr(n, s.length)
|
||||
}
|
27
src/tree/subtree-of-another-tree.js
Normal file
27
src/tree/subtree-of-another-tree.js
Normal file
@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Definition for a binary tree node.
|
||||
* function TreeNode(val, left, right) {
|
||||
* this.val = (val===undefined ? 0 : val)
|
||||
* this.left = (left===undefined ? null : left)
|
||||
* this.right = (right===undefined ? null : right)
|
||||
* }
|
||||
*/
|
||||
/**
|
||||
* @param {TreeNode} s
|
||||
* @param {TreeNode} t
|
||||
* @return {boolean}
|
||||
*/
|
||||
export const isSubtree = function (s, t) {
|
||||
if (!s && t) {
|
||||
return false
|
||||
}
|
||||
|
||||
const linkNode = function (node, target) {
|
||||
if ((!node && target) || (node && !target)) return false
|
||||
if (!node && !target) return true
|
||||
|
||||
return node.val === target.val ? linkNode(node.left, target.left) && linkNode(node.right, target.right) : false
|
||||
}
|
||||
|
||||
return linkNode(s, t) || isSubtree(s.left, t) || isSubtree(s.right, t)
|
||||
}
|
15
test/array/maximal-square.test.js
Normal file
15
test/array/maximal-square.test.js
Normal file
@ -0,0 +1,15 @@
|
||||
import { maximalSquare } from '../../src/array/maximal-square'
|
||||
|
||||
test('最大正方形', () => {
|
||||
expect(maximalSquare([
|
||||
[1, 0, 1, 0, 0],
|
||||
[1, 0, 1, 1, 1],
|
||||
[1, 1, 1, 1, 1],
|
||||
[1, 0, 0, 1, 0]
|
||||
])).toBe(4)
|
||||
|
||||
expect(maximalSquare([
|
||||
[0, 0, 0],
|
||||
[1, 1, 1]
|
||||
])).toBe(1)
|
||||
})
|
6
test/array/minimum-cost-for-tickets.test.js
Normal file
6
test/array/minimum-cost-for-tickets.test.js
Normal file
@ -0,0 +1,6 @@
|
||||
import { mincostTickets } from '../../src/array/minimum-cost-for-tickets'
|
||||
|
||||
test('最低票价', () => {
|
||||
expect(mincostTickets([1, 4, 6, 7, 8, 20], [2, 7, 15])).toBe(11)
|
||||
expect(mincostTickets([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 30, 31], [2, 7, 15])).toBe(17)
|
||||
})
|
24
test/list/linked-list-cycle.test.js
Normal file
24
test/list/linked-list-cycle.test.js
Normal file
@ -0,0 +1,24 @@
|
||||
import { hasCycle } from '../../src/list/linked-list-cycle'
|
||||
|
||||
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('环形链表', () => {
|
||||
const list = arrToList([1, 2, 3])
|
||||
list.next.next.next = list
|
||||
expect(hasCycle(list)).toBe(true)
|
||||
expect(hasCycle(arrToList([1, 2, 3]))).toBe(false)
|
||||
})
|
6
test/string/zuo-xuan-zhuan-zi-fu-chuan-lcof.test.js
Normal file
6
test/string/zuo-xuan-zhuan-zi-fu-chuan-lcof.test.js
Normal file
@ -0,0 +1,6 @@
|
||||
import { reverseLeftWords } from '../../src/string/zuo-xuan-zhuan-zi-fu-chuan-lcof'
|
||||
|
||||
test('左旋转字符串', () => {
|
||||
expect(reverseLeftWords('abcdefg', 2)).toBe('cdefgab')
|
||||
expect(reverseLeftWords('lrloseumgh', 6)).toBe('umghlrlose')
|
||||
})
|
7
test/tree/subtree-of-another-tree.test.js
Normal file
7
test/tree/subtree-of-another-tree.test.js
Normal file
@ -0,0 +1,7 @@
|
||||
import { isSubtree } from '../../src/tree/subtree-of-another-tree'
|
||||
import Tree from './Tree'
|
||||
|
||||
test('另一个树的子树', () => {
|
||||
expect(isSubtree(Tree.arrToTree([3, 4, 5, 1, 2]), Tree.arrToTree([4, 1, 2]))).toBe(true)
|
||||
expect(isSubtree(Tree.arrToTree([3, 4, 5, 1, 2, null, null, null, null, 0]), Tree.arrToTree([4, 1, 2]))).toBe(false)
|
||||
})
|
Loading…
Reference in New Issue
Block a user