js-sdsl - 一款参考 C++ STL 编写的 JavaScript 数据结构库
内含使用 RB-tree 实现的 Set,Map 以及哈希表、优先队列等多种数据结构,拥有极度完整的单元测试和性能测试以及完整的 api 文档
支持 CommonJS 和 ES modules,同时支持浏览器 script 标签引入,采用 TypeScript 编写,具有严谨的类型推导
尽管 JavaScript 出现了很多年,但是一直没有一套标准的库来实现或包含高级数据结构,这对一种语言来说是不幸的事件,我们想通过编写这个库来弥补这一缺陷
对于 LeetCode 的用户来说,如果你是一位前端开发人员(例如我),有了它后不必再去学习新的语言,例如 C++、Java 或 Python,而可以通过这个库来更高效率的在 LeetCode 上学习
这道题想必大家都不陌生,使用堆/优先队列可以完美的完成它,不过如果你是 Js 或 Ts 的使用者,你会发现无法使用原生的功能来实现,通过使用 js-sdsl 我们可以轻松的解决它,就像这样
import { PriorityQueue } from "js-sdsl";
function findKthLargest(nums: number[], k: number): number {
const que = new PriorityQueue(nums);
while (--k) que.pop();
return que.top();
};我们来看一道更复杂的题目,第 303 场周赛的 C 题
显然这道题可以使用哈希表和排序树进行求解,可惜的是 Js 并不提供平衡树相关的数据结构,而使用 js-sdsl 可以很好的解决这一问题,例如
import { HashMap, OrderedSet } from "js-sdsl";
class FoodRatings {
private foodMap: HashMap<string, [number, string]>;
private CuisineMap: HashMap<string, OrderedSet<[number, string]>>;
constructor(foods: string[], cuisines: string[], ratings: number[]) {
// define the compare function
const cmp = (foodX: [number, string], foodY: [number, string]) => {
if (foodX[0] < foodY[0]) return 1;
if (foodX[0] > foodY[0]) return -1;
const len = Math.min(foodX[1].length, foodY[1].length);
for (let i = 0; i < len; ++i) {
if (foodX[1][i] < foodY[1][i]) return -1;
if (foodX[1][i] > foodY[1][i]) return 1;
}
return 0;
};
this.foodMap = new HashMap();
this.CuisineMap = new HashMap();
// init our map
cuisines.forEach((cuisine, index) => {
this.foodMap.setElement(foods[index], [ratings[index], cuisine]);
const set = this.CuisineMap.getElementByKey(cuisine);
if (set === undefined) {
this.CuisineMap.setElement(cuisine,
new OrderedSet([
[ratings[index], foods[index]
] as [number, string]], cmp));
} else {
set.insert([ratings[index], foods[index]]);
}
});
}
changeRating(food: string, newRating: number): void {
const [rating, cuisine] = this.foodMap.getElementByKey(food) as [number, string];
const set = this.CuisineMap.getElementByKey(cuisine);
this.foodMap.setElement(food, [newRating, cuisine]);
set?.eraseElementByKey([rating, food]);
set?.insert([newRating, food]);
}
highestRated(cuisine: string): string {
// @ts-ignore
// there may get undefined, but this question is guaranteed to have an answer.
return this.CuisineMap.getElementByKey(cuisine)?.getElementByPos(0)?.[1];
}
}
const foodRatings = new FoodRatings(["kimchi", "miso", "sushi", "moussaka", "ramen", "bulgogi"], ["korean", "japanese", "japanese", "greek", "japanese", "korean"], [9, 12, 8, 15, 14, 7]);
console.log(foodRatings.highestRated("korean"));
console.log(foodRatings.highestRated("japanese"));
foodRatings.changeRating("sushi", 16);
console.log(foodRatings.highestRated("japanese"));
foodRatings.changeRating("ramen", 16);
console.log(foodRatings.highestRated("japanese"));
/*
* kimchi
* ramen
* sushi
* ramen
*/在这里发帖的原因有两个:
如果 LeetCode 官方有幸能看到这一建议并且愿意尝试的话,我们会非常荣幸与您合作!
最后附上项目地址:
github 链接:https://github.com/ZLY201/js-sdsl
npm 链接:https://www.npmjs.com/package/js-sdsl