寻找满足和为定值的两个数
2014-09-26 08:04
218 查看
参考:http://blog.csdn.net/v_JULY_v/article/details/6419466
https://github.com/julycoding/The-Art-Of-Programming-By-July/blob/master/ebook/zh/02.03.md
上面是大牛,我现在也是对着他的博客系列一篇篇在学习
寻找满足和为定值的两个数
一、算法思想:
例如对于给定数组 {1、2、4、7、11、15} 和 sum = 15,要求我们找出数组中满足和为sum的一对数。在有序和无序情况下,处理起来有所分别。O(n2)暴搜我就不说了
1、排序+二分查找
我们可以穷举第一个数,那对于第二个数如何确定?可以通过排序后进行二分查找获得。这样的时间复杂度是O(nlogn) 空间复杂度是O(1)
2、哈希表,这里用C++的unorder_map
同样循环每次确定第一个数a[i],然后利用hash表查找sum-a[i]是否在数组中。利用哈希表一个好处就是不用排序, 时间复杂度也降到了 O(n),但是需要 的空间复杂度O(n)
3、两个指针逼近法
OK,有没有更神奇的办法?利用两个指针一趟就能扫描所有的组合情况?有的,但是这种方法必须基于数组是有序的情况。在对数组排序后的情况下,一个头指针i,一个尾指针j,i只能向后移动,j只能向前移动。
如果a[i]+a[j]==sum 返回相应的两个数
如果a[i]+a[j]<sum 试图使求和变大些,则i向后移动一个试试(这里不能用j++,因为j+1的情况已经处理过了,要让两个指针遍历完所有的情况,j就只能往前,i只能往后,否则情况就太乱了,放心,这样子是一定能找到满足条件的值的,因为它能遍历完所有的情况)
如果a[i]+a[j]>sum 试图使求和变小些,则j向前移动
时间复杂度O(nlogn) 空间复杂度O(1)
二、若是要求我们返回下标,而不是具体数值呢?
个人觉得这时候如果数组本身有序,就利用思路三,两指针逼近法;若数组本身无序,则思路二,hasp表这时候最方便了。不可先排序后处理,这时候下标已经改变了,直接用上述方法得到的结果就不正确了。
https://github.com/julycoding/The-Art-Of-Programming-By-July/blob/master/ebook/zh/02.03.md
上面是大牛,我现在也是对着他的博客系列一篇篇在学习
寻找满足和为定值的两个数
一、算法思想:
例如对于给定数组 {1、2、4、7、11、15} 和 sum = 15,要求我们找出数组中满足和为sum的一对数。在有序和无序情况下,处理起来有所分别。O(n2)暴搜我就不说了
1、排序+二分查找
我们可以穷举第一个数,那对于第二个数如何确定?可以通过排序后进行二分查找获得。这样的时间复杂度是O(nlogn) 空间复杂度是O(1)
vector<int> twoSum_v1(int a[], int n, int sum) { sort(a, a+n); vector<int> res; for(int i = 0; i < n; ++ i) { int x = sum - a[i]; int left = i + 1, right = n - 1, mid; while(left <= right) { mid = (left + right) / 2; if(a[mid] == x) break; else if(a[mid] < x) left = mid + 1; else right = mid - 1; } if(left <= right) { res.push_back(a[i]); res.push_back(a[mid]); break; } } return res; }
2、哈希表,这里用C++的unorder_map
同样循环每次确定第一个数a[i],然后利用hash表查找sum-a[i]是否在数组中。利用哈希表一个好处就是不用排序, 时间复杂度也降到了 O(n),但是需要 的空间复杂度O(n)
//unorder_map 哈希表实现 vector<int> twoSum_v2(int a[], int n, int sum) { unordered_map<int,bool> exist; vector<int> res; for(int i = 0; i < n; ++ i) exist[a[i]] = true; for(int i = 0; i < n; ++ i) { int x = sum - a[i]; if(exist.find(x) != exist.end()) { res.push_back(a[i]); res.push_back(x); break; } } return res; }
3、两个指针逼近法
OK,有没有更神奇的办法?利用两个指针一趟就能扫描所有的组合情况?有的,但是这种方法必须基于数组是有序的情况。在对数组排序后的情况下,一个头指针i,一个尾指针j,i只能向后移动,j只能向前移动。
如果a[i]+a[j]==sum 返回相应的两个数
如果a[i]+a[j]<sum 试图使求和变大些,则i向后移动一个试试(这里不能用j++,因为j+1的情况已经处理过了,要让两个指针遍历完所有的情况,j就只能往前,i只能往后,否则情况就太乱了,放心,这样子是一定能找到满足条件的值的,因为它能遍历完所有的情况)
如果a[i]+a[j]>sum 试图使求和变小些,则j向前移动
时间复杂度O(nlogn) 空间复杂度O(1)
//两个指针两端扫描实现 vector<int> twoSum_v3(int a[], int n, int sum) { vector<int> res; sort(a, a + n); int i = 0, j = n -1; while( i < j) { if(a[i] + a[j] == sum) { res.push_back(a[i]); res.push_back(a[j]); break; } else if(a[i] + a[j] < sum) { ++i; } else --j; } return res; }
二、若是要求我们返回下标,而不是具体数值呢?
个人觉得这时候如果数组本身有序,就利用思路三,两指针逼近法;若数组本身无序,则思路二,hasp表这时候最方便了。不可先排序后处理,这时候下标已经改变了,直接用上述方法得到的结果就不正确了。
相关文章推荐
- 寻找数组中满足和为定值的两个数或所有可能组合
- 编程之美2.12 快速寻找满足条件的两个数
- (10)寻找满足和为定值的两个或多个数
- 快速寻找满足条件的两个数
- 快速寻找满足条件的两个数(两数之和为给定值)
- 快速寻找满足条件的两个数(待完成)
- 编程之美2.12—快速寻找满足条件的两个数
- 快速寻找满足条件的两个数
- 编程之美_010快速寻找满足条件的两个数
- 编程之美2.12--快速寻找满足条件的两个数
- 编程之美2.12——快速寻找满足条件的两个数或三个数
- 快速寻找满足条件的两个数
- 快速寻找满足条件的两个数
- 编程之美1.12 —— 寻找满足条件的两个数、三个数
- 快速寻找满足条件的两个数
- 编程之美2.12——快速寻找满足条件的两个数或三个数
- [编程之美]快速寻找满足条件的两个数
- 院版每日一题(1) 快速寻找满足条件的两个数
- 寻找满足条件的两个数
- 编程之美 2.12 快速寻找满足条件的两个数