• 高速寻找满足条件的两个数


    时间:2014.07.17

    地点:基地

    -------------------------------------------------------------------------------------

    一、问题描写叙述

      给定一个数组。要求高速查找出当中的两个值。他们的和为一个给定的值。

    比方给定数组:1 4 5 6 8  9,和给定值9。我们能找出4+5=9为所要的数值

    -------------------------------------------------------------------------------------

    二、各种解法

    2.1穷举法

      对给定集合从中取出随意值求和,看是否等于给定和值,显然由组合公式知:其复杂度为N(N-1)/2,即O(N^2)。我们要求尽可能减少算法时间复杂度和算法空间复杂度,这个算法比較原始。

    2.2先排序后查找

      假定给定数字和为sum,对数组中的每一个数字arr[i],理想上是要有另外一个数字sum-arr[i]存在数组中即为查找成功。于是问题转换成了一个查找问题。而我们知道查找算法中最快的莫过于二分查找。时间复杂度为O(logN),但二分查找的前提是有序序列,于是我们要先对数组进行排序。我们也知道快排、堆排、归排等都是时间复杂度为O(NlogN)的排序算法。于是针对数组中的每一个数arr[i],都须要花费O(logN)的时间去查找相应的sum-arr[i]是否存在,于是总的时间复杂度为O(NlogN),在这里我们排序也需耗时O(NlogN)。但好在排序仅仅需一次。于是时间复杂度依然还是O(NlogN)。

    使用二分查找时要注意:

    1.将数组划分为两个子部分时,中间分界为:

    middle=first+size/2

    2.左边子部分可能略多,从first開始,大小为size/2

    3.右边子部分可能略少,从middle+1開始,大小为(size-1)/2

    2.3使用哈希查找

      在2.2节,我们已经将问题转换成了查找问题。其实,对于查找问题,若不惜代价追求速度的话,哈希查找最快,每次查找时间复杂度为O(1),于是在这里我们仅仅需O(N)就可以完毕任务。

    此种方法须要添加额外的存储空间。

    2.4双端扫描

      首先若数组无序。排序还是要排,时间复杂度为O(NlogN)。但若数组有序,则可直接O(N)完毕任务,在这里我们如果数组是有序的,如今才用双指针双端扫描法对整个数组扫描的策略:
    首先,设定两个指针begin 和 end。分别指向数组首和尾,

    然后,逐次推断arr[*begin]+arr[*end]和给定的sum进行大小比較

    i.若大于,说明两数和过大。运行--end,缩减两数和

    ii.若小于。说明两数和过小,运行++begin。放大两数和

    iii.若等于,正是我们所要。返回这个数值对

    双端扫描的代码例如以下:

    pair FindSumPair(int* arr, int n, int sum)
    {
    	//Sort(arr,arr+n);               //若数组无序,则先对数组进行排序
    	int* begin = arr;
    	int* end = arr + n - 1;
    	int tem_sum = 0;
    	while (begin < end)
    	{
    		tem_sum = (*begin) + (*end);
    		if (tem_sum>sum)
    			--end;
    		else if (tem_sum < sum)
    			++begin;
    		else
    			return pair(*begin, *end);
    	}
    	return pair(-1, -1);
    }

    -------------------------------------------------------------------------------------

    三、扩展

    2010年中兴面试题-编程求解:
    输入两个整数 n 和 m。从数列1,2,3.......n 中 随意取几个数,
    使其和等于 m, 要求将当中全部的可能组合列出来。


    引用算法之道JULY博客中的代码例如以下:

    #include<list>  
    #include<iostream>  
    using namespace std;  
      
    list<int>list1;  
    void find_factor(int sum, int n)   
    {  
        // 递归出口  
        if(n <= 0 || sum <= 0)  
            return;  
          
        // 输出找到的结果  
        if(sum == n)  
        {  
            // 反转list  
            list1.reverse();  
            for(list<int>::iterator iter = list1.begin(); iter != list1.end(); iter++)  
                cout << *iter << " + ";  
            cout << n << endl;  
            list1.reverse();      
        }  
          
        list1.push_front(n);      //典型的01背包问题  
        find_factor(sum-n, n-1);   //放n。n-1个数填满sum-n  
        list1.pop_front();  
        find_factor(sum, n-1);     //不放n。n-1个数填满sum   
    }  
      
    int main()  
    {  
        int sum, n;  
        cout << "请输入你要等于多少的数值sum:" << endl;  
        cin >> sum;  
        cout << "请输入你要从1.....n数列中取值的n:" << endl;  
        cin >> n;  
        cout << "全部可能的序列。例如以下:" << endl;  
        find_factor(sum,n);  
        return 0;  
    }  



  • 相关阅读:
    Android开发进阶——自定义View的使用及其原理探索
    Android开发——通过wifi接收IPCamera视频流
    (数据科学学习手札84)基于geopandas的空间数据分析——空间计算篇(上)
    (数据科学学习手札83)基于geopandas的空间数据分析——geoplot篇(下)
    (数据科学学习手札82)基于geopandas的空间数据分析——geoplot篇(上)
    (数据科学学习手札81)conda+jupyter玩转数据科学环境搭建
    (数据科学学习手札80)用Python编写小工具下载OSM路网数据
    (数据科学学习手札79)基于geopandas的空间数据分析——深入浅出分层设色
    实用的Python(3)超简单!基于Python搭建个人“云盘”
    (数据科学学习手札78)基于geopandas的空间数据分析——基础可视化
  • 原文地址:https://www.cnblogs.com/ldxsuanfa/p/10956577.html
  • Copyright © 2020-2023  润新知