zoukankan      html  css  js  c++  java
  • 二分练习题9 和为给定数 题解

    题目描述

    给出若干个整数,询问其中是否有一对数的和等于给定的数。

    输入格式

    共三行:
    第一行是整数 (n(0 lt n le 100000)) ,表示有 (n) 个整数。
    第二行是n个整数。整数的范围是在 (0)(10^8) 之间。
    第三行是一个整数 (m(0 le m le 2^{30})) ,表示需要得到的和。

    输出格式

    若存在和为m的数对,输出两个整数,小的在前,大的在后,中间用单个空格隔开。若有多个数对满足条件,选择数对中较小的数更小的。若找不到符合要求的数对,输出一行“NO”。

    样例输入

    4
    2 5 1 4
    6
    

    样例输出

    1 5
    

    题目分析

    这道题目可以使用时间复杂度为 (O(n)) 的双指针法。(有兴趣的同学可以了解一下)
    但是我们这里先来讲解 (O(nlogn)) 的二分解法。
    对于数组 (a_1,a_2,...,a_n) 来说,首先我们需要使用 sort 函数给他们从小到大排序。
    然后我们可以从 (1)(n) 遍历坐标 (i) ,对于 (a[i]) 来说,我们可以在 ([i+1, n]) 这个区间范围内使用二分来查找是否存在一个元素等于 (m-a[i])
    当然咯,我们遍历的时候也要保证 (a[i] le m/2) 就可以了,因为我二分查找的另一个元素肯定 (le a[i])
    实现代码如下:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 100010;
    int n, m, a[maxn];
    // check函数用于二分查找数组a[L,R]中是否存在值为num的元素
    bool check(int num, int L, int R) {
        while (L <= R) {
            int mid = (L + R) / 2;
            if (a[mid] == num) return true;
            else if (a[mid] > num) R = mid - 1;
            else L = mid + 1;
        }
        return false;
    }
    int main() {
        cin >> n;
        for (int i = 1; i <= n; i ++) cin >> a[i];
        cin >> m;
        sort(a+1, a+1+n);   // 给数组a[1]到a[n]范围内的数从小到大排序
        for (int i = 1; i <= n && a[i] <= m/2; i ++) { // 开始遍历a[i]
            if (check(m - a[i], i+1, n)) {  // 对[i+1,n]区间范围内二分查找m-a[i]
                cout << a[i] << " " << m-a[i] << endl;
                return 0;
            }
        }
        puts("NO");
        return 0;
    }
    
  • 相关阅读:
    建站手册-网站主机:电子商务主机
    建站手册-网站主机:网站主机的类型
    建站手册-网站主机:网站主机的数据库技术
    建站手册-网站主机:网站主机的服务器技术
    建站手册-网站主机:主机的电子邮件服务
    建站手册-网站主机:主机性能
    建站手册-网站主机:注册域名
    建站手册-网站主机:网站主机服务商
    建站手册-网站主机:网站主机介绍
    杂项:JFB-权限设置
  • 原文地址:https://www.cnblogs.com/zifeiynoip/p/11450637.html
Copyright © 2011-2022 走看看