add: 用两个栈实现队列

This commit is contained in:
yi-ge 2020-06-30 18:43:25 +08:00
commit 3115552b87
17 changed files with 248 additions and 0 deletions

View File

@ -353,6 +353,29 @@ LeetCode 与 LintCode 解题记录。此为个人练习仓库,代码中对重
- 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/stack/maximal-rectangle.js)
@ -369,6 +392,11 @@ LeetCode 与 LintCode 解题记录。此为个人练习仓库,代码中对重
- 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)
@ -419,6 +447,16 @@ LeetCode 与 LintCode 解题记录。此为个人练习仓库,代码中对重
- 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)【未完成】

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
}

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

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,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('')
}

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

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 { 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')
})