/**
* @param {number[]} target
* @return {boolean}
* 本题没有溢出
* 1. 每一轮替换后最大的数是替换前整个数组的和,当前数组最大的数就是上一轮被替换的数
* 2.如果被替换的数被替换前也是最大的数, 那么多次这样的替换过程中多个数组和的差值相等。这个用于加速计算。
* 3.逆着算, 计算target数组能不能退化成全部由1组成的数组
*/
var isPossible = function(target) {
if(target.length === 1) return target[0] === 1
let queue = new PriorityQueue()
let total = 0
for(let x of target) {
total += x
queue.push(x)
}
while(!queue.isEmpty()) {
let x = queue.peek()
if(x === 1) break
// s - (sum - s)
if((2 * x - total) < 1) return false
queue.pop()
let y = queue.peek()
let k = -1
let left = total - x
if(y === 1) {
k = (x - 1) / left
} else k = Math.ceil((x - y) / left)
x -= k * left
if(x <= 0) return false
total -= k * left
queue.push(x)
}
return true
};
function PriorityQueue(){
this.queue = new Array()
}
/**
* 本优先队列大元素放数组后面,小元素放数组前面
* splice指定哪个位置就会删除和添加到哪个位置, 所以添加时当前位置
* 元素后移, 删除时后面元素前移
*/
PriorityQueue.prototype.push = function(x) {
if(this.queue.length === 0) {
this.queue.push(x)
return
}
let l = 0
let r = this.queue.length
while(l < r) {
const m = ((l + r) / 2) | 0
if(this.queue[m] <= x) {
l = m + 1
} else if(this.queue[m] > x) {
r = m
}
}
this.queue.splice(l, 0, x)
}
PriorityQueue.prototype.peek = function(){
return this.queue[this.queue.length - 1]
}
PriorityQueue.prototype.pop = function(){
return this.queue.pop()
}
PriorityQueue.prototype.isEmpty = function(){
return this.queue.length === 0
}