• 九度OJ 1352:和为S的两个数字 (查找)


    时间限制:2 秒

    内存限制:32 兆

    特殊判题:

    提交:3160

    解决:833

    题目描述:
    输入一个递增排序的数组和一个数字S,在数组中查找两个数,是的他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。
    输入:
    每个测试案例包括两行:
    第一行包含一个整数n和k,n表示数组中的元素个数,k表示两数之和。其中1 <= n <= 10^6,k为int
    第二行包含n个整数,每个数组均为int类型。
    输出:
    对应每个测试案例,输出两个数,小的先输出。如果找不到,则输出“-1 -1”
    样例输入:
    6 15
    1 2 4 7 11 15
    样例输出:
    4 11

    思路:

    朴素思路是遍历查找,也就是我最初代码中用的方法。复杂度NlogN。

    但后来想想,其实根据4xy = (x+y)^2-(x-y)^2,两个数的和一定,那么差越大,积越小,其实只需要找差最大的这一对数即可。可以省掉很多多余的查找。但最坏的复杂度仍然是NlogN。

    进一步的优化思路能够将复杂度下降到线性:两个数A和B分别从最左侧和最右侧向中间搜索,每次循环中,固定A,从上次搜索到的B开始下降搜索。最终的复杂度将是N。

    PS:这个题的测试数据不是太好,我试了朴素思路和优化思路,结果竟然相差不大。


    代码:

    #include <stdio.h>
     
    #define N 1000000
     
    int search(int *a, int begin, int end, int x)
    {
        int len = end - begin;
        if (len <= 0)
            return -1;
        if (len == 1)
        {
            if (a[begin] == x)
                return begin;
            else
                return -1;
        }
     
        int mid = begin + len/2;
        if (a[mid] == x)
            return mid;
        else if (x < a[mid])
            return search(a, begin, mid, x);
        else
            return search(a, mid+1, end, x);
    }
     
    int main(void)
    {
        int n, k, i, j;
        int a[N];
     
        while (scanf("%d%d", &n, &k) != EOF)
        {
            for(i=0; i<n; i++)
                scanf("%d", &a[i]);
     
            for (i=0; i<n-1; i++)
            {
                j = search(a, i+1, n, k-a[i]);
                if (j > i)
                    break;
                else
                    continue;
            }
     
            if (i == n-1)
                printf("-1 -1
    ");
            else
                printf("%d %d
    ", a[i], a[j]);
        }
     
        return 0;
    }
    /**************************************************************
        Problem: 1352
        User: liangrx06
        Language: C
        Result: Accepted
        Time:1520 ms
        Memory:4748 kb
    ****************************************************************/

    优化代码:

    <pre name="code" class="cpp">#include <stdio.h>
     
    #define N 1000000
     
    int main(void)
    {
        int n, k, i, j;
        int a[N];
     
        while (scanf("%d%d", &n, &k) != EOF)
        {
            for(i=0; i<n; i++)
                scanf("%d", &a[i]);
     
            i = 0, j = n-1;
            while (i < j) {
                if (a[i] + a[j] == k)
                    break;
                else if (a[i] + a[j] < k)
                    i++;
                else
                    j--;
            }
     
            if (i == j)
                printf("-1 -1
    ");
            else
                printf("%d %d
    ", a[i], a[j]);
        }
     
        return 0;
    }
    /**************************************************************
        Problem: 1352
        User: liangrx06
        Language: C
        Result: Accepted
        Time:1450 ms
        Memory:4748 kb
    ****************************************************************/


    
    

  • 相关阅读:
    centos6.4下django1.11.3项目的部署
    inner join和left join 、right join 的区别?
    php中的对象赋值
    windows下Call to undefined function curl_init() error问题
    include和require的区别误区
    第一车网笔试题
    借贷宝笔试题
    40斤西瓜3人分,求分法
    走楼梯算法
    ip地址分类
  • 原文地址:https://www.cnblogs.com/liangrx06/p/5083781.html
Copyright © 2020-2023  润新知