快速选择满足条件的两个数
2014-04-16 22:37
211 查看
http://www.cnblogs.com/bingwenst/archive/2012/05/22/2513151.html
(原来解答三是这样)
能否快速找出一个数组中的两个数字,让这两个数字之和等于一个给定的值,
为了简化起见,我们假设这个数组中肯定存在至少一组符合要求的解。
假如有如下的两个数组:
5,6,1,4,7,9,8
给定Sum= 10
1,5,6,7,8,9
给定Sum= 10
解法三
还可以换个角度来考虑问题,假设已经有了这个数组的任意两个元素之和的有
序数组(长为N^2)。那么利用二分查找法,只需用O(2*log2N)就可以解决这个
问题。当然不太可能去计算这个有序数组,因为它需要O(N^2)的时间。但这个思
考仍启发我们,可以直接对两个数字的和进行一个有序的遍历,从而降低算法的时
间复杂度。
首先对数组进行排序,时间复杂度为(N*log2N)。
然后令i = 0,j = n-1,看arr[i] + arr[j] 是否等于Sum,如果是,则结束。如果小于
Sum,则i = i + 1;如果大于大于Sum,则 j = j – 1。这样只需要在排好序的数组上遍
历一次,就可以得到最后的结果,时间复杂度为O(N)。两步加起来总的时间复杂
度O(N*log2N)
刚开始一直无法理解这样一定可以找到这个和吗?难道不会漏掉了解的位置。可
以这么理解,假如排好序后的数组为1,3,6,a,9,12,17,28,b,35,46 ,那么i最初指向1的位
置,j最初指向46的位置,比如所求的是Sum=a+b,a<b,a和b在数组中的某位置上。
那么i和j在变化过程中,只考虑i遇到了a或者j遇到了b的时候,必定有一个先遇到,
比如i遇到了a,那么这个时候j必定还没指到b,故这是j指到的值比b大,从而j减小直
到b位置。同理若j先指到了b位置,那么i必定还没指到a(这是我们的前提),然后i现
在指到的值比a小,故i增加,直到a位置。
扩展问题
1、如果把这个问题中的“两个数字”改成“三个数字”或“任意个数字”时,你的解是什
么呢?
三个数字:首先还是先对数组进行排序,然后从 i=0到 n-1 进行遍历,遍历arr[i]时,在
调用上面的函数getSumNum(arr , Sum-arr[i])即可。
任意m个数字的想法:
首先数组排序,然后从 i=0到n-1 个元素遍历,遍历arr[i]时,在剩下的n-1个元素中调
用 getSumNum(arr,Sum-arr[i]),此时为求 m-1 个元素和为 Sum-arr[i];接下来,同样的方法,
从 j=0 到 n-2 个元素遍历,遍历 arr[j]时在 arr 上递归调用 getSumNum(arr,Sum-arr[i]-arr[j]),
此时为求 m-2 个元素和为 Sum-arr[i]-arr[j];依次递归,直到为求 2 个元素和为 Sum-?-?-?...
时为止。
不论是求 3 个数字还好是 m 个数字,总是能比较穷举法少一个数量级 n,比先排序然
后二分查找求Sum-arr[i]也要快。
(原来解答三是这样)
能否快速找出一个数组中的两个数字,让这两个数字之和等于一个给定的值,
为了简化起见,我们假设这个数组中肯定存在至少一组符合要求的解。
假如有如下的两个数组:
5,6,1,4,7,9,8
给定Sum= 10
1,5,6,7,8,9
给定Sum= 10
解法三
还可以换个角度来考虑问题,假设已经有了这个数组的任意两个元素之和的有
序数组(长为N^2)。那么利用二分查找法,只需用O(2*log2N)就可以解决这个
问题。当然不太可能去计算这个有序数组,因为它需要O(N^2)的时间。但这个思
考仍启发我们,可以直接对两个数字的和进行一个有序的遍历,从而降低算法的时
间复杂度。
首先对数组进行排序,时间复杂度为(N*log2N)。
然后令i = 0,j = n-1,看arr[i] + arr[j] 是否等于Sum,如果是,则结束。如果小于
Sum,则i = i + 1;如果大于大于Sum,则 j = j – 1。这样只需要在排好序的数组上遍
历一次,就可以得到最后的结果,时间复杂度为O(N)。两步加起来总的时间复杂
度O(N*log2N)
刚开始一直无法理解这样一定可以找到这个和吗?难道不会漏掉了解的位置。可
以这么理解,假如排好序后的数组为1,3,6,a,9,12,17,28,b,35,46 ,那么i最初指向1的位
置,j最初指向46的位置,比如所求的是Sum=a+b,a<b,a和b在数组中的某位置上。
那么i和j在变化过程中,只考虑i遇到了a或者j遇到了b的时候,必定有一个先遇到,
比如i遇到了a,那么这个时候j必定还没指到b,故这是j指到的值比b大,从而j减小直
到b位置。同理若j先指到了b位置,那么i必定还没指到a(这是我们的前提),然后i现
在指到的值比a小,故i增加,直到a位置。
扩展问题
1、如果把这个问题中的“两个数字”改成“三个数字”或“任意个数字”时,你的解是什
么呢?
三个数字:首先还是先对数组进行排序,然后从 i=0到 n-1 进行遍历,遍历arr[i]时,在
调用上面的函数getSumNum(arr , Sum-arr[i])即可。
任意m个数字的想法:
首先数组排序,然后从 i=0到n-1 个元素遍历,遍历arr[i]时,在剩下的n-1个元素中调
用 getSumNum(arr,Sum-arr[i]),此时为求 m-1 个元素和为 Sum-arr[i];接下来,同样的方法,
从 j=0 到 n-2 个元素遍历,遍历 arr[j]时在 arr 上递归调用 getSumNum(arr,Sum-arr[i]-arr[j]),
此时为求 m-2 个元素和为 Sum-arr[i]-arr[j];依次递归,直到为求 2 个元素和为 Sum-?-?-?...
时为止。
不论是求 3 个数字还好是 m 个数字,总是能比较穷举法少一个数量级 n,比先排序然
后二分查找求Sum-arr[i]也要快。
相关文章推荐
- 编程之美---快速寻找满足条件的两个数---扩展问题
- LeetCode-Two Sum(编程之美-快速寻找满足条件的两个数字)
- 编程之美 2.12 快速寻找满足条件的两个数 解法三证明 (算法导论 第二版 2.3-7 在n个元素的集合S中找到两个和为x的元素)
- 【codeforces 691 E】【矩阵快速幂 思维题】【给定序列,从序列中选择k个数(可以重复选择),使得得到的排列满足xi与xi+1异或的二进制表示中1的个数是3的倍数。问满足条件的序列个数】
- 编程之美-2.12-快速寻找满足条件的两个数
- 快速满足条件的两个数
- 快速寻找满足条件的两个数字
- 编程之美2.12——快速寻找满足条件的两个数。(拓展满足条件的多个数)
- 编程之美 快速寻找满足条件的两个或多个数
- 快速寻找满足条件的两个数
- 2.12快速寻找满足条件的两个数---程序员编程艺术之五
- 《编程之美》:快速寻找满足条件的两个数
- 编程之美2.12快速寻找满足条件的两个数及扩展问题Java版
- 快速寻找满足条件的两个数(待完成)
- 第2章 数字之魅——快速寻找满足条件的两个数
- 编程之美2.12——快速寻找满足条件的两个数或三个数
- 满足条件的两个数或多个数
- 查找介于n1与n2(0<n1<n2<32768)之间所有满足下列条件的整数: (1)该数的十进制表示中有且仅有两个相同的数字位; (2)该数是素数
- @陈利人 : #面试题#给定两个数组X和Y,元素都是正数。请找出满足如下条件的数对的数目: x^y > y^x,即x的y次方>y的x次方;x来自X数组,y来自Y数组
- 编程之美2.12 快速寻找满足条件的两个数