zoukankan      html  css  js  c++  java
  • 编程之美-快速寻找满足条件的2 个数

    能否快速找出一个数组中的两个数字,让这个两个数字之和等于一个给定的值,为了简化起见,我们假设这个数组中肯定至少存在一组满足要求的解。

    作者给出了3种方案:

    [方案一]穷举法:从数组任意取出两个数字,计算两者之和是否为给定的数字。时间复杂度O(N^2),效率较低。

    [方案二]将问题变通为一个查找问题:求两个数之和,假定为sum。对于数组中的每个数array[i],判断sum-array[i]是否在数组中。在一个无序数组中查找一个数的复杂度是O(N),对于每个数字都要进行相应的查找,则时间复杂度仍为O(N^2)。为了提高效率,可以相对数组进行排序,然后利用二分查找算法,时间复杂度为O(NlogN)。

    [方案三]利用hash表提高查找效率,因为给定一个数字,根据hash映射查找另一个数字是否在数组中,只需用O(1)的时间,查找时间为O(1),总的时间复杂度就为O(N)。但是这会使得空间复杂度也为O(N)。

    [方案四]先对数组进行排序,然后对数组中的两个数之和进行一个有序的遍历。具体算法:先令i=0,j=n-1,判断array[i]+array[j]是否等于sum,如相等则结束;如小于则i向右移动一个位置,否则j向左移动一个位置。这样时间复杂度为排序O(NlogN)+查找O(N) = O(N(logN+1))

    [扩展问题1]:如果将“两个数字”改为“三个数字”或“任意个数字”时,如何求解?

    [方案]对于“三个数字”其实就是对于数组中的每个数字array[i]判断数组中的其他数字是否存在两个数字的和为sum-array[i],以此递归下去。

    int index = 0;
    bool find(int array[], int n, int start, int m, int sum, int result[]){
        assert(m >= 2);
        if(n-start < m)
            return false;
        int i,j;
        if(m == 2){
            for(i=start,j=n;i<j;){
                if(array[i] + array[j] == sum){
                    result[index++] = array[i];
                    result[index++] = array[j];
                    return true;
                }
                else if(array[i] + array[j] < sum)
                    i++;
                else
                    j--;
            }
            return false;
        }else{
            for(i=start;i<n;i++){
                result[index++] = array[i];
                if(find(array,n,i+1,m-1,sum - array[i],result)){
                    return true;
                }
                index--;
            }
            return false;
        }
        return false;
    }

    [扩展问题2]:如果完全相等的一对数字找不到,能否找出和最接近的解? 算法实现(C语言):

    void findNearest(int array[], int n, int sum, int result[]){
        int i,j;
        int minDiff = INT_MAX;
        for(i=0,j=n-1;i<j;){
            if(array[i]+array[j] == sum){
                result[0] = array[i];
                result[1] = array[j];
                return;
            }else{
                int diff = array[i]+array[j] -sum;
                int tmp_i = array[i];
                int tmp_j = array[j];
                if(diff > 0)
                    j--;
                else{
                    i++;
                    diff = -diff;
                }
                if(diff < minDiff){
                    minDiff = diff;
                    result[0] = tmp_i;
                    result[1] = tmp_j;
                }
            }
        }
    }

    转自:http://blog.csdn.net/andyliuxs/article/details/7537128

    给定一个数N和一组数字集合S,在S中找到和最接近N的子集。

    更多:http://blog.csdn.net/wxl3105/article/details/7651579

  • 相关阅读:
    PHP 安装配置
    网络,进程 相关指令
    大数据之路:阿里巴巴大数据实践PDF下载
    计算机系统概论PDF下载
    计算机组成与体系结构性能设计PDF下载
    简明python教程PDF下载
    软件工程-实践者的研究方法PDF下载
    软件测试PDF下载
    设计模式解析PDF下载
    设计原本pdf下载
  • 原文地址:https://www.cnblogs.com/youxin/p/3367398.html
Copyright © 2011-2022 走看看