寻找和为定值的两个数
时间:2022-04-22
本文章向大家介绍寻找和为定值的两个数,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
题目:输入一个数组和一个数字,在数组中查找两个数,使得它们的和正好是输入的那个数字。 要求时间复杂度是O(n)。如果有多对数字的和等于输入的数字,输出任意一对即可。 例如输入数组1、2、4、7、11、15和数字15。由于4+11=15,因此输出4和11。
解析:如果数组是无序的,先排序(n*logn),然后用两个指针i,j,各自指向数组的首尾两端,令i=0,j=n-1,然后i++,j--,逐次判断 a[i]+a[j]?=sum,如果某一刻a[i]+a[j]>sum,则要想办法让sum的值减小,所以此刻i不动,j--,如果某一刻 a[i]+a[j]<sum,则要想办法让sum的值增大,所以此刻i++,j不动。所以,数组无序的时候,时间复杂度最终为 O(n*logn+n)=O(n*logn),若原数组是有序的,则不需要事先的排序,直接O(n)搞定,且空间复杂度还是O(1),此思路是相对于上述 所有思路的一种改进。(如果有序,直接两个指针两端扫描,时间O(N),如果无序,先排序后两端扫描,时间O(N*logN+N)=O(N*logN),空间始终都为O(1))。
总结:
- 不论原序列是有序还是无序,解决这类题有以下三种办法:1、二分(若无序,先排 序后二分),时间复杂度总为O(n*logn),空间复杂度为O(1);2、扫描一遍X-S[i] 映射到一个数组或构造hash表,时间复杂度为O(n),空间复杂度为O(n);3、两个指针两端扫描(若无序,先排序后扫描),时间复杂度最后为:有序 O(n),无序O(n*logn+n)=O(n*logn),空间复杂度都为O(1)。
- 所以,要想达到时间O(N),空间O(1)的目 标,除非原数组是有序的(指针扫描法),不然,当数组无序的话,就只能先排序,后指针扫描法或二分(时间n*logn,空间O(1)),或映射或 hash(时间O(n),空间O(n))。时间或空间,必须牺牲一个,自个权衡吧。
- 综上,若是数组有序的情况下,优先考虑两个指针两端扫描法,以达到最佳的时(O(N)),空(O(1))效应。否则,如果要排序的话,时间复杂度最快当然是只能达到N*logN,空间O(1)则是不在话下。
这里假定数组已经是有序的,代码可以如下编写(两段代码实现):
bool FindNumbersWithSum(int data[], int length, int sum, int *num1, int *num2)
{
bool found = false;
if(length < 1 || num1 == NULL || num2 == NULL)
return false;
int ahead = length - 1;
int behind = 0;
while(ahead > behind)
{
long long curSum = data[ahead] + data[behind];
if(curSum == sum)
{
*num1 = data[behind];
*num2 = data[ahead];
found = true;
break;
}
else if(curSum > sum)
ahead--;
else
behind++;
}
return found;
}
测试代码:
1 #include<iostream>
2 using namespace std;
3
4 bool find_num(int data[] , int length , int sum , int &first_num , int &second_num)
5 {
6 if(length < 1)
7 return true;
8
9 int begin = 0;
10 int end = length - 1;
11
12 while(begin < end)
13 {
14 int current_sum = data[begin] + data[end];
15
16 if(current_sum == sum)
17 {
18 first_num = data[begin];
19 second_num = data[end];
20 return true;
21 }
22 else if(current_sum > sum)
23 end--;
24 else
25 begin++;
26 }
27 return false;
28 }
29
30 int main()
31 {
32 int data[] = {1 , 2 , 4 , 7 , 11 , 15};
33 int length = sizeof(data)/sizeof(int);
34 int first_num = 0 ;
35 int second_num = 0;
36 int sum = 15;
37
38 if(find_num(data , length , 15 , first_num , second_num))
39 {
40 cout<<first_num<<" "<<second_num<<endl;
41 }
42 else
43 cout<<"not exist!"<<endl;
44
45 return 0;
46 }
寻找和为定值的多个数:
2010年中兴面试题编程求解:输入两个整数 n 和 m,从数列1,2,3.......n 中 随意取几个数,使其和等于 m ,要求将其中所有的可能组合列出来。 |
---|
1 #include<list>
2 #include<iostream>
3 using namespace std;
4
5 list<int>list1;
6 void find_factor(int sum, int n)
7 {
8 // 递归出口
9 if(n <= 0 || sum <= 0)
10 return;
11
12 // 输出找到的结果
13 if(sum == n)
14 {
15 // 反转list
16 list1.reverse();
17 for(list<int>::iterator iter = list1.begin(); iter != list1.end(); iter++)
18 cout << *iter << " + ";
19 cout << n << endl;
20 list1.reverse();
21 }
22
23 list1.push_front(n); //典型的01背包问题
24 find_factor(sum-n, n-1); //放n,n-1个数填满sum-n
25 list1.pop_front();
26 find_factor(sum, n-1); //不放n,n-1个数填满sum
27 }
28
29 int main()
30 {
31 int sum, n;
32 cout << "请输入你要等于多少的数值sum:" << endl;
33 cin >> sum;
34 cout << "请输入你要从1.....n数列中取值的n:" << endl;
35 cin >> n;
36 cout << "所有可能的序列,如下:" << endl;
37 find_factor(sum,n);
38 return 0;
39 }
参考:http://blog.csdn.net/v_JULY_v/article/details/6419466
- Redis安全小结
- webpack学习(七)打包压缩图片
- POJ1275 Cashier Employment(差分约束)
- REDIS操作命令小结
- Java发送邮件工具类
- javascript 变量、作用域和内存问题
- 1726: [Usaco2006 Nov]Roadblocks第二短路
- vue小白快速入门
- 算法模板——线段树9(区间加+区间求和+区间方和)
- 1709: [Usaco2007 Oct]Super Paintball超级弹珠
- 2015: [Usaco2010 Feb]Chocolate Giving
- 2060: [Usaco2010 Nov]Visiting Cows 拜访奶牛
- 2020: [Usaco2010 Jan]Buying Feed, II
- 2102: [Usaco2010 Dec]The Trough Game
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- c++之普通函数和模板函数的区别
- 【python-leetcode15-双指针】三个数之和为零
- 百度easydl之图像分类构建是否佩戴口罩模型
- c++之普通函数和模板函数的调用规则
- 解决github打不开问题
- vuejs之第一个vue程序
- c++之函数模板的局限性
- c++之模板-类模板
- springboot监控之监控管理
- c++之类模板和函数模板的区别
- 【python-leetcode977-双指针】有序数组的平方
- springboot分布式之springcloud-Eureka注册中心
- c++之类模板成员函数创建时机
- vuejs之v-on小例子之实现购买数量的增加和减少
- c++之类模板对象作函数参数