top1编程
← 返回题目
题解

在数组中找数

1 条题解

  • 0
    @ 2026-8-6 1:17:21

    P4780 在数组中找数(基础)

    解题思路

    第一步,弄清楚题目要干什么。 题目先给出 N 个整数,就像一本只有数字的“字典”,然后有 M 次询问,每次问一个数 d 在这本“字典”里出现过没有。出现过输出 Yes,没出现过输出 No。

    第二步,先想一个最笨的办法。 每次询问都把 N 个数从头到尾扫一遍,遇到相等的数就说明找到了。这个方法虽然简单,但如果 N 和 M 都很大,最坏要做 M 乘 N 次比较,非常慢,就像查一本没有目录的字典,每次都要翻完整本书,太浪费时间了。

    第三步,想到“先排序,再二分查找”。 我们先把 N 个数从小到大排好序,这样数组就有了大小顺序。有了顺序,就能用二分查找快速判断一个数在不在数组里。

    第四步,理解二分查找。 二分查找就像猜数字游戏:对方心里想一个 1 到 100 之间的数,你猜 50,对方说“大了”,你就知道答案在 1 到 49 之间,再猜 25……每猜一次,可能的范围就缩小一半。查找也一样:每次看当前范围正中间的数 nums[mid],如果它正好等于 d,就找到了;如果它比 d 小,说明 d 一定在右半边,把左边界 left 挪到 mid+1;如果它比 d 大,说明 d 在左半边,把右边界 right 挪到 mid-1。

    第五步,处理找不到的情况。 如果范围不断缩小,最后 left 已经大于 right,说明整个数组都找遍了也没有 d,此时输出 No。

    第六步,举一个例子。 数组是 1 2 3,要查 1。第一次看中间位置 nums[1]=2,比 1 大,只看左半边;再看 nums[0]=1,正好相等,输出 Yes。要查 4:范围越缩越小,最后 left 大于 right,输出 No。

    参考代码

    // 在数组中找数:先把 N 个整数排序,再对每个询问用二分查找判断该数是否出现过
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    int nums[2000005];
    
    int main() {
        int n, m;
        scanf("%d%d", &n, &m);
        for (int i = 0; i < n; i++) {
            scanf("%d", &nums[i]);
        }
        // 先从小到大排序,之后才能用二分查找
        sort(nums, nums + n);
        for (int query = 0; query < m; query++) {
            int d;
            scanf("%d", &d);
            // 在有序数组 nums 中二分查找 d 是否存在
            int left = 0, right = n - 1;
            bool found = false;
            while (left <= right) {
                int mid = (left + right) / 2;
                if (nums[mid] == d) {
                    found = true;
                    break;
                } else if (nums[mid] < d) {
                    left = mid + 1;
                } else {
                    right = mid - 1;
                }
            }
            if (found) {
                printf("Yes\n");
            } else {
                printf("No\n");
            }
        }
        return 0;
    }
    

    复杂度分析

    排序需要 O(N log N) 的时间;每次询问二分查找只需要比较 O(log N) 个数,M 次询问一共 O(M log N)。所以总时间复杂度是 O(N log N + M log N),即使 N、M 都达到 10 万也很快。空间上只需要存 N 个数的数组,是 O(N)。

    • 1