剑指offer 2.20

81 阅读2分钟

剑指 Offer 41. 数据流中的中位数

// js没有堆结构真的太伤了,注意在两个堆都为空时,虽然是向min插入,但是后面插入到了max,所以元素数为奇数时是返回max的堆顶元素。在Insert时,先插入到哪个堆与后面的中位数值对应即可。
var MedianFinder = function () {
    class Heap {
        constructor(cmp = (x, y) => x < y) {
            this.arr = [];
            this.arr.push(0);
            this.cmp = cmp;
        }
        sink() {
            let index = 1;
            while (index * 2 < this.arr.length) {
                let left = index * 2;
                const tmp = this.arr[index];
                if ((left + 1) < this.arr.length && this.cmp(this.arr[left + 1], this.arr[left]/*&&this.cmp(this.arr[left+1],tmp)*/)) {
                    this.arr[index] = this.arr[left + 1];
                    index = left + 1;
                    this.arr[index] = tmp;
                    continue;
                    // 这里有个逻辑错误
                    //右子节点大于左子节点也不一定右子结点大于根节点
                    //但是由于sink是把堆尾的元素向前移动的
                    //所以代码居然ac了?
                    //这个地方加上右子节点和根节点的比较更严谨一点
                }
                if (this.cmp(this.arr[left], tmp)) {
                    this.arr[index] = this.arr[left];
                    this.arr[left] = tmp;
                    index = left;
                    continue;
                }
                break;
            }
        }
        swim() {
            let index = this.arr.length - 1;
            while (index > 1 && this.cmp(this.arr[index], this.arr[Math.floor(index / 2)])) {
                const tmp = this.arr[index];
                this.arr[index] = this.arr[Math.floor(index / 2)];
                this.arr[Math.floor(index / 2)] = tmp;
                index = Math.floor(index / 2);
            }
        }
        push(val) {
            this.arr.push(val);
            this.swim();
        }
        pop() {
            const store = this.arr[1];
            this.arr[1] = this.arr[this.arr.length - 1];
            this.arr.pop();
            this.sink();
            return store;
        }
        peak() {
            return this.arr[1] ? this.arr[1] : 0;
        }
        size() {
            return this.arr.length-1;
        }
    }
    this.min = new Heap();// 存储较大值
    this.max = new Heap((x, y) => x > y);// 存储较小值
};

/** 
 * @param {number} num
 * @return {void}
 */
MedianFinder.prototype.addNum = function (num) {
    if (this.min.size() != this.max.size()) {
        this.max.push(num);
        this.min.push(this.max.pop());
    }
    else {
        this.min.push(num);
        this.max.push(this.min.pop());
    }
};

/**
 * @return {number}
 */
MedianFinder.prototype.findMedian = function () {
    console.log(this.min.peak() , this.max.peak())
    return this.min.size() == this.max.size() ? (this.min.peak() + this.max.peak()) / 2 : this.max.peak();
};

剑指 Offer 55 - II. 平衡二叉树

//自底向上,如果在第一次不平衡时能直接返回效率会更高一点。
var isBalanced = function(root) {
    return helper(root)!=-1;
};
var helper = (root)=>{
    if(!root) return 0;
    if(helper(root.left)==-1){
        return -1;
    }
    if(helper(root.right)==-1){
        return -1;
    }
    return Math.abs(helper(root.left)-helper(root.right))>1?-1:Math.max(helper(root.left),helper(root.right))+1;
}

剑指 Offer 68 - II. 二叉树的最近公共祖先

// 找到递归的终止条件,和判断标准即可。更新公共祖先需要两节点分别在左右子树中,或者某个节点在另一个结点的子树中。
var lowestCommonAncestor = function (root, p, q) {
    let ans = root;
    let help = (root)=>{
        if(!root) return false;
        let left = help(root.left);
        let right = help(root.right);
        if((left&&right)||(root==p||root==q)&&(left||right)){
            ans = root;
        }
        return left||right||root==p||root==q;// 为了能遍历到p和q
    }
    help(root);
    return ans;
};

剑指 Offer 33. 二叉搜索树的后序遍历序列

// 注意边界条件,找到一个大于根节点则后面的必须都大于根节点,否则就不平衡了。
var verifyPostorder = function(postorder) {
    if(postorder.length==0) return true;
    let dfs = (i,j)=>{
        if(i>=j) return true;
        let mid = i;
        while(postorder[mid]<postorder[j]) mid++;
        let right = mid;
        while(postorder[right]>postorder[j]) right++;
        return right==j&&dfs(i,mid-1)&&dfs(mid,j-1);
    }
    return dfs(0,postorder.length-1)
};