【剑指offer学习】求和为定值的两个数

《神雕侠侣》中的‘剑冢’,收存着‘剑魔独孤求败’生平用过的三把剑:“杨过提起右首第一柄剑,只见剑下的石上刻有两行小字‘凌厉刚猛,无坚不摧,弱冠前以之与河朔群雄争锋’;第二把是玄铁重剑:‘重剑无锋,大巧不工。四十岁前恃之横行天下’;第三把则是木剑,剑下的石刻道:‘四十岁后,不滞于物,草木竹石均可为剑。自此精修,渐进于无剑胜有剑之境。’。算法的精髓也在于此,只有突破一层层境界,才能有所突破。

题目描述:

输入一个递增排序的数组和一个数字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)。

实现代码如下:

<span style="font-size:18px;">// offer01.cpp : 定义控制台应用程序的入口点。
//

#include "stdio.h"

//在升序数组A中找出和为sum的任意两个元素,并且保存在a和b中
bool FindNumSum(int *A,int len,int sum,int *a,int *b)
{
	if(A==NULL||len<2||A[0]>sum)
		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;

}

//main 函数
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 isFind=FindNumSum(A,n,k,&a,&b);
		if(isFind)
			printf("%d %d\n",a,b);
		else
			printf("-1 -1\n");
	}

	return 0;
}

</span>

参考一些资料:

针对该方法需要给出一些证明,证明如下:

该方法对任意的整数数组都适合,另外,要输出乘积最小的一组,没必要将所有的结果保存起来。

当a+b = c时,ab<=(a+b)^2/4,当且仅当a==b时,ab取得最大值,二者相差越远,乘积越小。

时间: 2024-10-25 05:08:01

【剑指offer学习】求和为定值的两个数的相关文章

【剑指offer】和为定值的连续正数序列

转载请注明出处:http://blog.csdn.net/ns_code/article/details/27823291 题目描写叙述: 小明非常喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他立即就写出了正确答案是100.可是他并不满足于此,他在想到底有多少种连续的正数序列的和为100(至少包含两个数).没多久,他就得到还有一组连续正数和为100的序列:18,19,20,21,22.如今把问题交给你,你能不能也非常快的找出全部和为S的连续正数序列? Good Luck! 输入:

【剑指Offer学习】【所有面试题汇总】

剑指Offer学习 剑指Offer这本书已经学习完了,从中也学习到了不少的东西,现在做一个总的目录,供自已和大家一起参考,学如逆水行舟,不进则退.只有不断地学习才能跟上时候,跟得上技术的潮流! 所有代码下载[https://github.com/Wang-Jun-Chao/coding-interviews] 目录 第01-10题 [剑指Offer学习][面试题02:实现Singleton 模式--七种实现方式] [剑指Offer学习][面试题03:二维数组中的查找] [剑指Offer学习][面

【剑指offer】 堆排序查找最小的K个数

上一篇 说了些堆的建立及其相关操作,这里看下用堆来解决数据量较大的时候,查找最小的k个数的情况.这里会用到上一篇中的函数. 我们先生存1千万个随机数,写到文件中: import random def randData(): with open('randint.txt', 'w') as fd: for i in range(1, 10000000): fd.write('%d ' %random.randint(1, 100)) if i % 100 == 0: fd.write('\r')

【剑指offer】二进制中1的个数

题目描述: 请实现一个函数,输入一个整数,输出该数二进制表示中1的个数.例如把9表示成二进制是1001,有2位是1.因此如果输入9,该函数输出2. 分析描述: 1.对一个整数的二进制形式,要想知道其中1的个数,首先想到的应该就是遍历整个二进制数,用到的方法当然就是移动了(包含左移或右移).例如,用1来跟给定的整数做与运算.如果结果为1,则证明整数的二进制形式中,最右边的一位是1,如果结果是0,则证明整数的二进制形式中,最右边的一位是0. int NumberOf1(int n) { int co

剑指offer (10) 二进制中1的个数

题目:输入一个整数,输出该数二进制表示中1的个数. 我们可能很快写下如下代码: 1 int NumOf1InBinary(int n) 2 { 3 int count = 0; 4 while (n != 0) { 5 if (n & 1 ) { 6 ++count; 7 } 8 n >> 1; // bug!!! 9 } 10 return count; 11 } 第8行存在bug. 首先C/C++中数有无符号数和有符号数两种(我一直认为无符号数是个蛋疼的存在,滋生大量的bug) 左

剑指Offer:二进制中1的个数

题目:输入一个整数,输出该数二进制表示中1的个数. // 二进制中1的个数 #include <stdio.h> int wrong_count_1_bits(int n) // 错误解法: 当n为负数时, n>>=1右移, 最高位补1, 陷入死循环 { int count = 0; while(n) { if( n & 1 ) ++count; n >>= 1; } return count; } int count_1_bits(int n) // 常规解法

《剑指offer》 二进制中1的个数

本题来自<剑指offer> 二进制中1的个数 题目: 输入一个整数,输出该数二进制表示中1的个数.其中负数用补码表示. 思路: 两种思路: 第一种:对n进行左移,检测最后一位是否为1,但考虑负数,一直左移会陷入到死循环中. 第二种:对n的每一位进行检测,采用滑标flag,左移,int会是32位,所以会最多移动32次. C++ code1:(第二种思路) class Solution { public: int NumberOf1(int n) { //最多可以移动32次, int count=

剑指offer 42.和为S的两个数字

剑指offer 42.和为S的两个数字 题目 题目描述 输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的. 输出描述: 对应每个测试案例,输出两个数,小的先输出. 思路 同样是滑动窗口题目,设置左右两个游标,然后计算和,若和小,那么左侧游标增加,区间和大,右侧游标减小,保存结果的时候要比较一下更符合条件的数. 代码 public ArrayList<Integer> FindNumbersWithSum(int[]

[剑指Offer]41 和为S的两个数字 VS 和为S的连续正数序列

[剑指Offer]41 和为S的两个数字 VS 和为S的连续正数序列 Leetcode T1 Two Sum Given an array of integers, return indices of the two numbers such that they add up to a specific target. You may assume that each input would have exactly one solution, and you may not use the s

【剑指Offer学习】【面试题:二维数组中的查找】PHP实现

最近一直看剑指Offer.里面很多算法题.于是就想着用PHP来显示一下. 题目: 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序. 请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. 拿到这个题目.我们第一个反应,就是遍历二维数组.然后逐个进行比较.我们不难用PHP进行实现.于是有了下面的代码 1 function TwoArrayFind($array,$search) { 2 $found = false; 3 4 if(e