【剑指offer】和为定值的两个数
转载请注明出处:http://blog.csdn.net/ns_code/article/details/24933341
- 题目描写叙述:
- 输入一个递增排序的数组和一个数字S,在数组中查找两个数,是的他们的和正好是S。假设有多对数字的和等于S,输出两个数的乘积最小的。
- 输入:
-
每一个測试案例包括两行:第一行包括一个整数n和k,n表示数组中的元素个数,k表示两数之和。当中1 <= n <= 10^6,k为int第二行包括n个整数。每一个数组均为int类型。
- 输出:
- 相应每一个測试案例,输出两个数,小的先输出。假设找不到,则输出“-1 -1”
- 例子输入:
-
6 15
1 2 4 7 11 15
- 例子输出:
-
4 11
思路:
最直接的做法是暴力法,两个for循环,时间复杂度为O(n*n)。可是这样没有充分利用升序数组这一前提。我们假设数组为A,长度为len,给定的和为sum,最好的方法是先用数组的第一个数A[low]和最后一个数A[high]相加,看是否等于sum,假设等于sum。则找到了一组数。返回true,假设大于sum,则将较大的数向前移动一位,即high--,此时变成了第一个和倒数第二个数相加,假设小于sum,则将较小的数向后移动一位,即low++。此时变成了第二个和最后一个数相加。依此类推,假设low==high时还未找到和为sum的一组数,则返回false。
该算法的时间复杂度为O(n),空间复杂度为O(1)。
针对该方法须要给出一些证明,证明例如以下:
对于一个升序数列A1,A2,...Ak k>=3,假设A1+Ak大于sum。那么考察k-1个数对和A1+Ak,A2+Ak,...Ak-1+Ak有sum<A1+Ak<=A2+Ak<=,...<=Ak-1+Ak。也就是说,Ak与数列中其他不论什么数的和都不可能等于sum,因此抛弃Ak这个数,对结果没有影响。A1+Ak假设小于sum的话,同理抛弃A1这个数对结果没有影响。
该方法对随意的整数数组都适合。另外,要输出乘积最小的一组,不是必需将所有的结果保存起来,我们由以下我们高中时很熟悉的数学公式能够证明最左边和最右边的两个符合要求的数的乘积最小。
当a+b = c时,ab<=(a+b)的平方/4,当且仅当a==b时,ab取得最大值,二者相差越远,乘积越小。
aC代码例如以下:
/****************************************************************************************************
题目:输入一个已经按升序排序过的数组和一个数字,在数组中查找两个数,使得它们的和正好是输入的那个数字。 要求时间复杂度是O(n)。假设有多对数字的和等于输入的数字。输出随意一对就可以。
比如输入数组1、2、4、7、11、15和数字15。 因为4+11=15,因此输出4和11。
*****************************************************************************************************/
#include<stdio.h>
#include<stdbool.h>
/*
在升序数组A中找出和为sum的随意两个元素。保存在a和b中
*/
bool FindTwoNumSum(int *A,int len,int sum,int *a,int *b)
{
if(A==NULL || len<2)
return false;
int low = 0;
int high = len-1;
while(low<high)
{
if(A[low]+A[high] == sum)
{
*a = A[low];
*b = A[high];
return true;
}
else if(A[low]+A[high] < sum)
low++;
else
high--;
}
return false;
} int main()
{
int n,k;
static int A[1000000];
while(scanf("%d %d",&n,&k) != EOF)
{
int i;
for(i=0;i<n;i++)
scanf("%d",A+i); int a,b;
bool can = FindTwoNumSum(A,n,k,&a,&b);
if(can)
printf("%d %d\n",a,b);
else
printf("-1 -1\n");
} return 0;
}
/************************************************************** Problem: 1352 User: mmc_maodun Language: C Result: Accepted Time:1460 ms Memory:4820 kb****************************************************************/ 我们如今来拓展一下,假设数组是乱序的,并且规定数组中的元素所有为非负整数,相同给定一个数sum,在数组中找出随意两个数。使二者的和为sum。
或者假设知道非负整数数组A的最大值为MAX,则也能够开辟一个MAX大小的bool数组。思路是一样的。
/****************************************************************************************************
题目:输入一个无序的非负整数数组和一个数字,在数组中查找两个数,使得它们的和正好是输入的那个数字。
要求时间复杂度是O(n)。 假设有多对数字的和等于输入的数字。输出随意一对就可以。
比如输入数组1、7、4、11、6、15和数字15。因为4+11=15。因此输出4和11。 *****************************************************************************************************/
#include<stdio.h>
#include<stdlib.h> /*
在无序数组A中找出和为sum的随意两个元素。保存在a和b中
*/
bool FindTwoNumSum(int *A,int len,int sum,int *a,int *b)
{
if(A==NULL || len<2)
return false;
//各元素均被初始化为false的bool数组
bool *B = (bool*)calloc(sum,sizeof(bool));
if(B == NULL)
exit(EXIT_FAILURE);
int i;
for(i=0;i<len;i++)
{
if(A[i]>sum)
continue;
if(B[A[i]] == false)
B[sum-A[i]] = true;
else
{
*a = A[i];
*b = sum-A[i];
free(B);
B = NULL;
return true;
}
}
free(B);
B = NULL;
return false;
} int main()
{
int A[] = {19,3,9,7,12,20,17,18,1,16};
int len = 10;
int sum = 24;
int a,b;
if(FindTwoNumSum(A,len,sum,&a,&b))
printf("Find two nums,they are:\n%d and %d\n",a,b);
else
printf("Not find\n");
return 0;
}
測试结果:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbnNfY29kZQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" />
【剑指offer】和为定值的两个数的更多相关文章
- 剑指offer用位运算实现两个数相加,及python相关的位操作
题目:写一个函数,求两个整数之和,要求在函数体内不得使用+.-.*./四则运算符号. 代码: # -*- coding:utf-8 -*-class Solution: def Add(self ...
- 剑指Offer - 九度1509 - 树中两个结点的最低公共祖先
剑指Offer - 九度1509 - 树中两个结点的最低公共祖先2014-02-07 01:04 题目描述: 给定一棵树,同时给出树中的两个结点,求它们的最低公共祖先. 输入: 输入可能包含多个测试样 ...
- 剑指Offer - 九度1519 - 合并两个排序的链表
剑指Offer - 九度1519 - 合并两个排序的链表2013-11-30 22:04 题目描述: 输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则.(hi ...
- 剑指Offer - 九度1512 - 用两个栈实现队列
剑指Offer - 九度1512 - 用两个栈实现队列2013-11-29 21:23 题目描述: 用两个栈来实现一个队列,完成队列的Push和Pop操作.队列中的元素为int类型. 输入: 每个输入 ...
- leetcode 338. Counting Bits,剑指offer二进制中1的个数
leetcode是求当前所有数的二进制中1的个数,剑指offer上是求某一个数二进制中1的个数 https://www.cnblogs.com/grandyang/p/5294255.html 第三种 ...
- C++版 - 剑指offer之面试题37:两个链表的第一个公共结点[LeetCode 160] 解题报告
剑指offer之面试题37 两个链表的第一个公共结点 提交网址: http://www.nowcoder.com/practice/6ab1d9a29e88450685099d45c9e31e46?t ...
- 剑指Offer 和为S的两个数字
题目描述 输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的. 输出描述: 对应每个测试案例,输出两个数,小的先输出. 思路 ...
- 剑指Offer——和为S的两个数字
题目描述: 输入一个递增排序的数组和一个数字S,在数组中查找两个数,是的他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的. 输入描述: 对应每个测试案例,输出两个数,小的先输出. ...
- 剑指Offer——二进制中1的个数
题目描述: 输入一个整数,输出该数二进制表示中1的个数.其中负数用补码表示. 分析: 加入一个数的二进制位是XXX...XXX1000...000,那么这个数减去1,就会变成XXX...XXX0111 ...
- 剑指offer第二版-9.用两个栈实现队列
描述:使用两个栈实现一个队列.队列中实现尾部插入和头部删除函数. 思路:stack1负责插入,stack2负责弹出,如果stack2为空了,将stack1的元素依次弹出并存放到stack2中,之后对s ...
随机推荐
- Mockito简介(转)
Mockito 是目前 java 单测中使用比较流行的 mock 工具.其他还有 EasyMock,JMock,MockCreator,Mockrunner,MockMaker 及 PowerMock ...
- 拥抱AngularJS
文中一些地方AngularJS简称ng 简介: ng诞生于2009年,由Misko Hevery等创建,后被Google收购,为克服HTML在构建应用上的不足而设计. 是一款优秀的前端JS框架,核心特 ...
- SQL Server 存储过程、触发器、游标
存储过程 1.存储过程是事先编好的.存储在数据库中的程序,这些程序用来完成对数据库的指定操作. 2.系统存储过程: SQL Server本身提供了一些存储过程,用于管理有关数据库和用户的信息. 用户存 ...
- linux 解决Ubuntu编译内核uImage出现问题“mkimage” command not found - U-Boot images will not be built问题
解决Ubuntu编译内核uImage出现问题“mkimage” command not found - U-Boot images will not be built问题 http://www.lin ...
- C语言,题目:函数调用,内存,malloc找错
malloc int* p = (int *) malloc (sizeof(int)*128); //分配128个(可根据实际需要替换该数值)整型存储单元,并将这128个连续的整型存储单元的首地址存 ...
- Oracle数据库top10物理段
select owner, name, type, mega, tbs from (select owner, case when ...
- Juuluu 旗下企业站点管理系统3.0.1公布!
KgE金刚企业站点管理系统是广州聚龙软件为国内中小企业开发的一款企业站点管理系统,KgE採用可视化的标签模型,可在Dreamvear等网页编辑下可视化编辑,KgE使用javaeemsyqlyuijqu ...
- clearcase常用命令
版本控制工具学习 http://www.itpxpj.com/course.do?method=getAllCourseInFront&classTypeId=21 1.[ClearCase] ...
- PHP学习之-面向对象
PHP学习之-面向对象 1.什么是对象 "世界万物皆对象",一切可以被抽象出来的东西都是对象.像花,草.看不到的"概念"都是对象. 2.对象的基本组成 a.属性 ...
- PHP学习之-1.1 PHP 可以做什么?
PHP 可以做什么? 为什么要学习PHP,"我可以用javascript来实现程序的编写."但是javascript的能力是有限的,javascript通常运行在浏览器(客户端), ...