美文网首页工作生活
[AcWing] 789. 数的范围

[AcWing] 789. 数的范围

作者: _charlie_li | 来源:发表于2020-02-08 15:18 被阅读0次

    标签: 二分

    给定一个按照升序排列的长度为n的整数数组,以及 q 个查询。

    对于每个查询,返回一个元素k的起始位置和终止位置(位置从0开始计数)。

    如果数组中不存在该元素,则返回“-1 -1”。

    输入格式
    第一行包含整数n和q,表示数组长度和询问个数。

    第二行包含n个整数(均在1~10000范围内),表示完整数组。

    接下来q行,每行包含一个整数k,表示一个询问元素。

    输出格式
    共q行,每行包含两个整数,表示所求元素的起始位置和终止位置。

    如果数组中不存在该元素,则返回“-1 -1”。

    数据范围
    1≤n≤100000 1≤q≤10000 1≤k≤10000

    输入样例

    6 3
    1 2 2 3 3 4
    3
    4
    5
    

    输出样例

    3 4
    5 5
    -1 -1
    

    思路:

    没有思路的时候,想想暴力解法(当然这题可以看出是二分),前不久刚学了时间复杂度的估算(假设1s内可以计算10^8次):

    时间复杂度 1s内计算次数
    O(N) 10 ^ 8
    O(N ^ 2) 10 ^ 4
    O(lg N) 27
    /*
    暴力解法:超时,数据规模最高达到10^ 9
    */
    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N = 10e5 + 10;
    int main() {
        int n, m, arr[N], target;
        
        scanf("%d%d", &n, &m);
        for(int i = 0; i < n; i++) 
            scanf("%d", &arr[i]);
        
        while(m--) {
            scanf("%d", &target);
            
            int l = -1, r = -1;
            //左, 右边界 10 ^ 5 * 10 ^ 4, O(n)可能会超时,试试吧
            for(int i = 0; i < n; i++) {
                if(l == -1 && arr[i] == target) {
                    l = i;
                }
                
                if(i + 1 < n && arr[i + 1] != target && arr[i] == target) { //没有去找 n- 1的位置
                    r = i;
                }
            }
            
            if(arr[n - 1] == target) {
                r = n - 1;
            }
            
            //没有找到
            if(l == -1) {
                printf("-1 -1\n");
            } else {
                printf("%d %d\n", l, r);
            }
        }
        return 0;
    }
    
    /*
        二分解法
    */
    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N = 10e5 + 10;
    int main() {
        int n, m, arr[N], target;
        
        scanf("%d%d", &n, &m);
        for(int i = 0; i < n; i++) 
            scanf("%d", &arr[i]);
        
        while(m--) {
            scanf("%d", &target);
            
            //寻找左边界
            int l = 0, r = n - 1;
            while(l < r) {
                int mid = l + ((r - l) >> 1);
                
                if(arr[mid] < target) {
                    l = mid + 1;
                } else if(arr[mid] > target) {
                    r = mid - 1;
                } else {
                    r = mid;
                }
            }
            
            if(arr[l] != target) {  //区间中没有target
                cout << "-1 -1" << endl;
                continue;
            }
            
            cout << l << " ";
            
            //寻找右边界
            l = 0, r = n - 1;
            while(l < r) {
                int mid = l + ((r - l + 1) >> 1);
                
                if(arr[mid] < target) {
                    l = mid + 1;
                } else if(arr[mid] > target) {
                    r = mid - 1;
                } else {
                    l = mid;    //将数组分成[l, mid - 1], [mid + 1, r],所以 mid = l + ((r - l + 1) >> 1)
                }
            }
            
            cout << l << endl;
        }
        return 0;
    }
    

    相关文章

      网友评论

        本文标题:[AcWing] 789. 数的范围

        本文链接:https://www.haomeiwen.com/subject/gbphhctx.html