算法优化:从1天到1s

原文链接:http://lixing123.com/?p=285

最近参加了Coursera的课程,Stanford大学的《算法:设计与分析》。这是一门非常值得学习的课程。在老师布置的作业中,有这样一道题目:

The goal of this problem is to implement a variant of the 2-SUM algorithm .

The file contains 1 million integers, both positive and negative (there might be some repetitions!).This is your array of integers, with the ith row
of the file specifying the ith entry
of the array.

Your task is to compute the number of target values t in the interval [-10000,10000] (inclusive) such that there are distinct numbers x,yin
the input file that satisfy x+y=t.
(NOTE: ensuring distinctness requires a one-line addition to the algorithm from lecture.)

Write your numeric answer (an integer between 0 and 20001) in the space provided.

题目所提供的包含100万个integer的文件,我已经上传到这个github项目里-->点这里。这个项目就是此问题的Objective-C代码实现。

这是一种2-Sum问题。要解决这个问题,首先跳到我脑子中的,是最brute force的方法:遍历。将所有100万个integer都相互加一次,然后把它们的结果保存下来。这种做法简单粗暴,而且无效。因为它的渐近时间复杂度为O(n^2),具体到这个问题上,需要计算的次数至少为1,000,000^2=10^12。我试过运行这种brute force的程序,大概每0.1s可以针对某一个integer计算出所有其它数与它的和。所以大概需要1000000/3600/10>25小时,所以行不通。

我想到,既然题目要求的是,将结果在-10000~10000范围的记下来,也就是说,对于任意一个数x,只需要计算范围在-x+10000~-x-10000之内的数就可以了,可以先将所有这1000000个数排序。渐近时间复杂度在O(nlog(n))的排序算法有好几个,我选了一个之前实现过的merge sort算法。从理论上来说,这种算法应该是比较快的,但不知道是代码出错还是其他的原因,速度很快,5分钟之内没有结果。而且,这种方法也比较麻烦,即使排序好了,也需要各种指针,每计算一个数,就需要重新计算与之相加的数的范围,容易出错。

后来我又想到一种方法:首先我发现了,这些所有的数,它们的最小值是-99,999,887,310,最大 值是99,999,662,302,也就是在-10^11~1-^11之间。那么,我把所有这100万个数,放入5,000,000个数组中。对于一个数x,x/20000=i,就将x放到第i个数组中。比如,group[0]放的是-20,000~20,000的数,group[1]放的是-40,000~-20,000以及20,000~40,000。

那么对于group[1]里的任何一个数,都只需要计算它和顶多2个group里的数的和。比如,对于25,000,需要计算它和-35,000~-15,000的和,而这些数都包含在group[0]和group[1]里。

而且,integer的总数为1,000,000,而group却有5,000,000个,也就是说,绝大多数group里都只有0个或1个数,计算量会大大减少,渐近时间复杂度是O(n)。

而实际上,这种方法的速度也非常快:只用了大概1s左右的时间。

这就是我将一个问题的算法的运行时间,从超过1天,减少到1s左右的过程。

实现代码在这里:点这里。由于做的是iOS开发,所以用Objective-C实现了。

时间: 2024-08-13 17:52:52

算法优化:从1天到1s的相关文章

SQL Server 聚合函数算法优化技巧

Sql server聚合函数在实际工作中应对各种需求使用的还是很广泛的,对于聚合函数的优化自然也就成为了一个重点,一个程序优化的好不好直接决定了这个程序的声明周期.Sql server聚合函数对一组值执行计算并返回单一的值.聚合函数对一组值执行计算,并返回单个值.除了 COUNT 以外,聚合函数都会忽略空值. 聚合函数经常与 SELECT 语句的 GROUP BY 子句一起使用. v1.写在前面 如果有对Sql server聚合函数不熟或者忘记了的可以看我之前的一片博客.sql server 基

性能优化——算法优化

背景 由于某种原因,我们系统需要记录另一个系统中一个表里的id.但是,当我们记录完了以后,别人系统可能会删除那个表里的一些数据,这样的话,我们这边就多了一些无效数据,所以,我们必须的找到这些无效的id,然后将其删除. 开始,我们的实现是这样:我们将记录下来的所有id放在一个list里,然后传到另一个系统,他将他们已经删除的id返回.具体处理代码如下: <pre name="code" class="java">public String findDele

冒泡排序及其算法优化分析

1.基本冒泡排序 冒泡排序的基本思想:假设被排序的记录数组d[1...N]垂直竖立,将每个记录d[i]看作是一个气泡,那么重的气泡就会向下下沉,轻的气泡就会向上升.每次都是相邻的两个气泡d[i]和d[i+1]进行比较.如果d[i]>d[i+1],那么就交换两个气泡,然后在比较d[i+1]和d[i+2],以此类推,知道所有的气泡都有序排列.假设排序20,37,11,42,29. 第1次冒泡:20.37,11,42,29 d[0]和d[1]比较 第2次冒泡:20,11,37,42,29 d[1]和d

查找质数的算法优化版

package com.my.testPrimeNumber; import java.util.ArrayList; import java.util.List; public class PrimeNumber { public boolean isPrimeNum(int n) { //第一步过滤偶数,使范围减少一半 if(n==2) { return true; } else if(n%2==0) { return false; } //处理奇数,一个素数中不会有偶数因子,但是他的平方根

算法优化之车牌识别---车牌识别优化项

基于DM6437的车牌识别算法移植及优化 http://cdmd.cnki.com.cn/Article/CDMD-10701-1013114119.htm 5.1 车牌识别算法的移植52-54 5.1.1 车牌识别算法工程的创建52 5.1.2 算法的编译及调试52-53 5.1.3 算法的测试53-54 5.2 车牌程序设计54-55 5.2.1 图像采集和显示54 5.2.2 数据处理54-55 5.3 DSP算法优化概述55-59 5.3.1 DSP算法优化思想55-59 5.4 车牌识

剪枝算法(算法优化)

一:剪枝策略的寻找的方法 1)微观方法:从问题本身出发,发现剪枝条件 2)宏观方法:从整体出发,发现剪枝条件. 3)注意提高效率,这是关键,最重要的. 总之,剪枝策略,属于算法优化范畴:通常应用在DFS 和 BFS 搜索算法中:剪枝策略就是寻找过滤条件,提前减少不必要的搜索路径. 二:剪枝算法(算法优化) 1.简介 在搜索算法中优化中,剪枝,就是通过某种判断,避免一些不必要的遍历过程,形象的说,就是剪去了搜索树中的某些"枝条",故称剪枝.应用剪枝优化的核心问题是设计剪枝判断方法,即确定

算法优化:rgb向yuv的转化最优算法

朋友曾经给我推荐了一个有关代码优化的pdf文档<让你的软件飞起来>,看完之后,感受颇深.为了推广其,同时也为了自己加深印象,故将其总结为word文档.下面就是其的详细内容总结,希望能于己于人都有所帮助. 速度取决于算法 同样的事情,方法不一样,效果也不一样.比如,汽车引擎,可以让你的速度超越马车,却无法超越音速:涡轮引擎,可以轻松 超越音障,却无法飞出地球:如果有火箭发动机,就可以到达火星. 代码的运算速度取决于以下几个方面 1.  算法本身的复杂度,比如MPEG比JPEG复杂,JPEG比BM

TLD跟踪算法优化(一)并行化

才学疏浅,只言片语,只求志同道的朋友一起交流研究. 并行化不算是算法的改进,只是追求运行的实时性. 简要列举一个例子: TLD算法的C++版本源码里: LKTracker::trackf2f(const Mat& img1, const Mat& img2,vector<Point2f> &points1, vector<cv::Point2f> &points2){ bool LKTracker::trackf2f(const Mat& i

内部元素一一相应的集合的算法优化,从list到hashmap

说是算法优化,基本上是在吹牛,仅仅只是算是记录下,我写代码时候的思路.毕竟还是小菜鸟. 我要开一个party,与会者都是情侣,可是情侣并非一起过来的,而是有先有后,可是每位与会者来的时候都拿着一束鲜花,第一件事情就是送给自己的伴侣. 设计一个算法,最高效率的解决这个事情. 最開始的时候,是这种. import java.util.ArrayList; import java.util.List; public class TestParty { List<Person> persons = n

转变为灰度图像的算法优化及马赛克实现代码

彩色图像转为灰度图像: 1.三个颜色通道像素值加和取均值(B+G+R)/3: 2.三个通道按照公式:r*0.299+g*0.587+b*0.114 计算效率:定点大于浮点,+-  >  */,移位(左移<<为乘,右移>>为除)大于乘除,所以算法优化如下图: 注:浮点型转成整型会存在误差,右图为实现马赛克效果的图像(原理就是马赛克区域分成n个矩形框,每个框的所有像素都用该框区域的一个像素值代替)                   原文地址:https://www.cnblog