活跃农民
- 积分
- 509
- 大米
- 颗
- 鳄梨
- 个
- 水井
- 尺
- 蓝莓
- 颗
- 萝卜
- 根
- 小米
- 粒
- 学分
- 个
- 注册时间
- 2013-6-5
- 最后登录
- 1970-1-1
|
0227 3. Design Search Autocomplete System
// default to min heap conforming to Java's priority queue
// push, pop, top, size
class Heap {
constructor (data, compare) {
this.data = data || []
this.compare = compare || ((a, b) => a - b)
const lastParent = this.getParent(this.data.length - 1)
for (let i = lastParent; i >= 0; i--) {
this.siftDown(i)
}
}
getParent (i) {
return Math.trunc((i - 1) / 2)
}
swap (i, j) {
;[this.data[i], this.data[j]] = [this.data[j], this.data[i]]
}
siftDown (i) {
let min = i
const left = 2 * i + 1
const right = 2 * i + 2
for (let index of [left, right]) {
if (index < this.data.length && this.compare(this.data[index], this.data[min]) < 0) { // !!! min, not i
min = index
}
}
if (min !== i) {
this.swap(i, min)
this.siftDown(min)
}
}
siftUp (i) {
// found a bug???? if it is the only one, how do you siftUp?
// then parent is itself, just remove equal?
const parent = this.getParent(i)
if (this.compare(this.data[parent], this.data[i]) > 0) { // !!! remove === ?
this.swap(parent, i)
this.siftUp(parent)
}
}
get size () {
return this.data.length
}
peak () {
return this.data[0]
}
push (val) {
this.data.push(val)
this.siftUp(this.data.length - 1)
}
pop () {
if (this.size > 0) {
const val = this.peak()
this.swap(0, this.data.length - 1)
this.data.pop()
this.siftDown(0)
return val
} else {
throw new Error('Heap is empty')
}
}
}
module.exports = Heap
class MyTrieNode {
constructor () {
this.map = new Map()
this.isEnd = false
}
}
var AutocompleteSystem = function(sentences = [], times = []) {
this.root = new MyTrieNode()
this.map = new Map()
for (let i = 0; i < sentences.length; i++) {
this.insert(sentences[i])
const count = this.map.get(sentences[i]) || 0
this.map.set(sentences[i], count + times[i])
}
this.node = this.root
this.tmp = ''
};
AutocompleteSystem.prototype.insert = function (setence) {
let node = this.root
for (let c of setence) {
if (c === '#') {
break
}
if (node.map.has(c)) {
node = node.map.get(c)
} else {
const newNode = new MyTrieNode()
node.map.set(c, newNode)
node = newNode
}
}
node.isEnd = true
}
AutocompleteSystem.prototype.input = function(c) {
// when you input a character, we move the node down the trie for one node if it exist
// or set it to null if it doesn't?
if (c === '#') {
this.insert(this.tmp)
const count = this.map.get(this.tmp) || 0 // !!! need to guard with 0
this.map.set(this.tmp, count + 1)
this.node = this.root
this.tmp = ''
return []
}
this.tmp += c
if (this.node == null) {
return []
}
if (this.node.map.has(c)) {
this.node = this.node.map.get(c) // !!! this.node not node
// !!! you are looking for top biggest 3, so it is a max heap
const pq = new Heap([], ((str1, str2) => {
const val = this.map.get(str2) - this.map.get(str1) // !!!! for number you want max heap so you revers, but
// for pure string you just compare by lexicographical order no need to reverse
if (val === 0) {
if (str1 > str2) {
return 1
} else if (str1 < str2) {
return -1
} else {
return 0
}
} else {
return val
}
}))
findTop(this.tmp, this.node, pq)
const res = []
for (let i = 0; i < 3; i++) {
if (pq.size > 0) {
res.push(pq.pop())
}
}
return res
} else { // !!! you are missing this part shit!!!
this.node = null
return []
}
// put all of the strs into the pq
function findTop (str, node, pq) {
if (node.isEnd) {
pq.push(str)
}
for (let [c, cNode] of node.map.entries()) {
findTop(str + c, cNode, pq)
}
}
};
Important thing is to have the big picture written down in pseudo code first. |
|