Binary search (4) -- Find Right Interval,Count Complete Tree Nodes,Divide Two Integers

Find Right Interval

Given a set of intervals, for each of the interval i, check if there exists an interval j whose start point is bigger than or equal to the end point of the interval i, which can be called that j is on the "right" of i.

For any interval i, you need to store the minimum interval j's index, which means that the interval j has the minimum start point to build the "right" relationship for interval i. If the interval j doesn't exist, store -1 for the interval i. Finally, you need output the stored value of each interval as an array.

Note:

  1. You may assume the interval's end point is always bigger than its start point.
  2. You may assume none of these intervals have the same start point.

Example 1:

Input: [ [1,2] ]

Output: [-1]

Explanation: There is only one interval in the collection, so it outputs -1.

1. map: map内部实现了一个红黑树,该结构具有自动排序的功能,因此map内部的所有元素都是有序的,红黑树的每一个节点都代表着map的一个元素,因此,对于map进行的查找,删除,添加等一系列的操作都相当于是对红黑树进行这样的操作,故红黑树的效率决定了map的效率。

2. unordered_map: unordered_map内部实现了一个哈希表,因此其元素的排列顺序是杂乱的,无序的

3. 因为map是有序的,所以有lower_bound这种函数

    vector<int> findRightInterval(vector<Interval>& intervals) {
        vector<int> rst;
        map<int, int> index_map;
        for(int i = 0; i < intervals.size(); i++){
            int start = intervals[i].start;
            index_map[start] = i;
        }

        for(Interval in : intervals){
            auto it = index_map.lower_bound(in.end);  
            if (it != index_map.end()) rst.push_back(it->second);
            else rst.push_back(-1);
        }
        return rst;
    }



Count Complete Tree Nodes

Given a complete binary tree, count the number of nodes.

Definition of a complete binary tree from Wikipedia:
In a complete binary tree every level, except possibly the last, is completely filled, and all nodes in the last level are as far left as possible. It can have between 1 and 2h nodes inclusive at the last level h.

1. 完全二叉树:只有最下面的两层结点度能够小于2,并且最下面一层的结点都集中在该层最左边的若干位置的二叉树

2. 比较二叉树最左和最右深度,如果相等则为满二叉树,结点数为 2 ^ h - 1;如果不相等则需继续查找

3. countLeft和countRight是为了避免对子树深度的重复计算

4. 开始的想法是,先计算树的最大深度H,然后从右开始计算,相比满二叉树而言缺失的叶子结点,最后用2 ^ H - 1 - missCount。但是最后超时了,感觉原因是 遍历去寻找缺失的叶子太耗时了。就好比遍历与二分查找之间的区别。在极端情况下,二叉树最后一层只有一个结点。这种方式相当于把整棵树遍历了一遍;而比较深度的做法可以很快的计算右半部分满二叉树的结点数。

    int countLeft(TreeNode* root, int hl){   //代表父结点为左儿子
        if (root == NULL) return 0;
        TreeNode* r = root;
        int hr = 1;
        while(r->right != NULL){   //计算右子树深度
            r = r->right;
            hr++;
        } 
        if (hl == hr) return pow(2, hl) - 1; //该子树为满二叉树
        return 1 + countLeft(root->left, hl-1) + countNodes(root->right);   //左子树的深度无需重复计算,只需计算右子树深度
    }
    
    int countRight(TreeNode* root, int hr){
        if (root == NULL) return 0;
        TreeNode* r = root;
        int hl = 1;
        while(r->left != NULL){
            r = r->left;
            hl++;
        } 
        if (hl == hr) return pow(2, hl) - 1;
        return 1 + countNodes(root->left) + countRight(root->right, hr-1);
    }
    
    int countNodes(TreeNode* root) {
        if (root == NULL) return 0;
        TreeNode* r = root;
        int hl = 1, hr = 1;
        while(r->left != NULL){
            r = r->left;
            hl++;
        } 
        r = root;
        while(r->right != NULL){
            r = r->right;
            hr++;
        } 
        if (hl == hr) return pow(2, hl) - 1;
        return 1 + countLeft(root->left, hl-1) + countRight(root->right, hr-1);
    }


Divide Two Integers

Divide two integers without using multiplication, division and mod operator.
If it is overflow, return MAX_INT.


1. dividend = divisor * quotient + quota。除法即找dividend减去最多几个divisor仍然是大于等于0的。

2. 使用移位操作代替乘除运算符

3. 有点divide and conquer的思想。先处理一部分,再处理另一部分,然后综合几部分的结果。

    int divide(int dividend, int divisor) {
        if (!divisor || (dividend == INT_MIN && divisor == -1))
            return INT_MAX;
        int sign = (dividend < 0) ^ (divisor < 0) ? 0 : 1;  //0为负,1为正
        long did = labs(dividend);  //返回long型的绝对值
        long dis= labs(divisor);
        
        int quotient = 0;
        while (did >= dis){
            long tmp = dis, multi = 1;
            while (did >= (tmp << 1)){  //之所以要用long,是因为did为INT_MAX时,tmp << 1会越界形成死循环
                tmp <<= 1;
                multi <<= 1;
            }
            did -= tmp;
            quotient += multi;
        }
        return sign ? quotient : -quotient;
    }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值