|
| 1 | +var minimumCost = function (source, target, original, changed, cost) { |
| 2 | + let distances = new Array(26).fill(Infinity); |
| 3 | + |
| 4 | + const graph = distances.map(() => new Array()); |
| 5 | + for (let i = 0; i < original.length; i++) { |
| 6 | + const source = original[i].charCodeAt(0) - 97; |
| 7 | + const target = changed[i].charCodeAt(0) - 97; |
| 8 | + const weight = cost[i]; |
| 9 | + |
| 10 | + graph[source].push([target, weight]); |
| 11 | + } |
| 12 | + |
| 13 | + const storeDistances = new Array(26).fill(null); |
| 14 | + |
| 15 | + let total = 0; |
| 16 | + for (let i = 0; i < source.length; i++) { |
| 17 | + if (source[i] !== target[i]) { |
| 18 | + const from = source[i].charCodeAt(0) - 97; |
| 19 | + const to = target[i].charCodeAt(0) - 97; |
| 20 | + |
| 21 | + if (storeDistances[from]) { |
| 22 | + total += storeDistances[from][to]; |
| 23 | + continue; |
| 24 | + } |
| 25 | + |
| 26 | + distances[from] = 0; |
| 27 | + |
| 28 | + const heap = new MyPriorityQueue((a, b) => distances[a] < distances[b]); |
| 29 | + heap.push(from); |
| 30 | + |
| 31 | + while (!heap.isEmpty()) { |
| 32 | + const current = heap.pop(); |
| 33 | + |
| 34 | + const neighbors = graph[current]; |
| 35 | + for (let neighbor of neighbors) { |
| 36 | + const [target, weight] = neighbor; |
| 37 | + |
| 38 | + if (distances[current] + weight < distances[target]) { |
| 39 | + distances[target] = distances[current] + weight; |
| 40 | + heap.push(target); |
| 41 | + } |
| 42 | + } |
| 43 | + } |
| 44 | + |
| 45 | + storeDistances[from] = distances; |
| 46 | + total += distances[to]; |
| 47 | + distances = new Array(26).fill(Infinity); |
| 48 | + } |
| 49 | + } |
| 50 | + |
| 51 | + return total === Infinity ? -1 : total; |
| 52 | +}; |
| 53 | + |
| 54 | +class MyPriorityQueue { |
| 55 | + constructor(comparator = (a, b) => a > b) { |
| 56 | + this._heap = []; |
| 57 | + this._comparator = comparator; |
| 58 | + } |
| 59 | + |
| 60 | + size() { |
| 61 | + return this._heap.length; |
| 62 | + } |
| 63 | + |
| 64 | + isEmpty() { |
| 65 | + return this.size() === 0; |
| 66 | + } |
| 67 | + |
| 68 | + peek() { |
| 69 | + return this._heap[0]; |
| 70 | + } |
| 71 | + |
| 72 | + _parent(idx) { |
| 73 | + return Math.floor((idx - 1) / 2); |
| 74 | + } |
| 75 | + |
| 76 | + _leftChild(idx) { |
| 77 | + return 2 * idx + 1; |
| 78 | + } |
| 79 | + |
| 80 | + _rightChild(idx) { |
| 81 | + return 2 * idx + 2; |
| 82 | + } |
| 83 | + |
| 84 | + _swap(i, j) { |
| 85 | + [this._heap[i], this._heap[j]] = [this._heap[j], this._heap[i]]; |
| 86 | + } |
| 87 | + |
| 88 | + _compare(i, j) { |
| 89 | + return this._comparator(this._heap[i], this._heap[j]); |
| 90 | + } |
| 91 | + |
| 92 | + push(value) { |
| 93 | + this._heap.push(value); |
| 94 | + this._siftUp(); |
| 95 | + |
| 96 | + return this.size(); |
| 97 | + } |
| 98 | + |
| 99 | + _siftUp() { |
| 100 | + let nodeIdx = this.size() - 1; |
| 101 | + |
| 102 | + while (nodeIdx > 0 && this._compare(nodeIdx, this._parent(nodeIdx))) { |
| 103 | + this._swap(nodeIdx, this._parent(nodeIdx)); |
| 104 | + nodeIdx = this._parent(nodeIdx); |
| 105 | + } |
| 106 | + } |
| 107 | + |
| 108 | + pop() { |
| 109 | + if (this.size() > 1) { |
| 110 | + this._swap(0, this.size() - 1); |
| 111 | + } |
| 112 | + const poppedValue = this._heap.pop(); |
| 113 | + this._siftDown(); |
| 114 | + |
| 115 | + return poppedValue; |
| 116 | + } |
| 117 | + |
| 118 | + _siftDown() { |
| 119 | + let nodeIdx = 0; |
| 120 | + |
| 121 | + while ( |
| 122 | + (this._leftChild(nodeIdx) < this.size() && |
| 123 | + this._compare(this._leftChild(nodeIdx), nodeIdx)) || |
| 124 | + (this._rightChild(nodeIdx) < this.size() && |
| 125 | + this._compare(this._rightChild(nodeIdx), nodeIdx)) |
| 126 | + ) { |
| 127 | + const greaterChildIdx = |
| 128 | + this._rightChild(nodeIdx) < this.size() && |
| 129 | + this._compare(this._rightChild(nodeIdx), this._leftChild(nodeIdx)) |
| 130 | + ? this._rightChild(nodeIdx) |
| 131 | + : this._leftChild(nodeIdx); |
| 132 | + |
| 133 | + this._swap(greaterChildIdx, nodeIdx); |
| 134 | + nodeIdx = greaterChildIdx; |
| 135 | + } |
| 136 | + } |
| 137 | +} |
0 commit comments