在给定数组中,找出最先满足两个数的和等于给定数,输出这两个元素的下表

leetcode上的一道题目,虽然不难,但是考察了数据结构中很多的知识

Given an array of integers, find two numbers such that they add up to a specific target number.

The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are not zero-based.

You may assume that each input would have exactly one solution.

Input: numbers={2, 7, 11, 15}, target=9
Output: index1=1, index2=2

1) 找到 两个数的和=target即可

穷举法,列出双层循环,从第一个开始,找到比target小的数,从这个数之后找两个数和=target的数,这样做的所循环次数为N+(N-1)+(N-2)+...+1 = 1/2(N*(N+1)),即复杂度为O(n2),提交过去发现不对,超时,看来O(n2)复杂度太高了

2)找到 满足 target-numbers[i]的数

这种即查找,常见的查找算法即直接查找O(n)和折半查找O(log2n),对于一个无需数组的查找,对每个number[i],都要查看target-number[i]在不在数组中,复杂度为O(n2),折半需要先排序才能进行,用一种快速的排序算法( 堆排序,快速排序,O(log2n))

快速排序:快速排序的时间主要耗费在划分操作上,对长度为k的区间进行划分,共需k-1次关键字的比较。

最坏情况是每次划分选取的基准都是当前无序区中关键字最小(或最大)的记录,划分的结果是基准左边的子区间为空(或右边的子区间为空),而划分所得的另一个非空的子区间中记录数目,仅仅比划分前的无序区中记录个数减少一个。时间复杂度为O(n*n)

对于快速排序,其空间复杂度为O(logn),最坏情况下,空间复杂度为O(n),可以用pivot算法来将其降低到O(logn)(即对基本有序的数列进行随机选取一个基准点,不然每次都是左边或者右边序列为空)

在最好情况下,每次划分所取的基准都是当前无序区的"中值"记录,划分的结果是基准的左、右两个无序子区间的长度大致相等。总的关键字比较次数:O(nlog2n)

尽管快速排序的最坏时间为O(n2),但就平均性能而言,它是基于关键字比较的内部排序算法中速度最快者,快速排序亦因此而得名。它的平均时间复杂度为O(nlgn)。

另外附上一张排序的图:

回到上一话题,即,先排序,在进行选择,排序算法复杂度为 O(nlog2n),但幸好 只需一次,排序好之后,便可以进行O(nlog2n)的查找,最后还是O(nlog2n)

还有一种办法是构建一个哈希,哈希表建立表的时间复杂度为O(n),查找的复杂度为O(1),但需要O(n)的空间复杂度,所以这是一种空间换时间的办法,有时候会很有效,最后哈希加折半的办法,使得复杂度变为O(n)+O(log2n)即O(n)的时间+O(n)的空间

3)找到numbers中两两数之和

对一个数组中的数两两求和,其复杂度无疑是O(n*n),但换一种思路,先排序,对排序好的数组分别建立两个指针指向队头队尾,target大了,则j前移,小了则i后移,直到找到sum记下两个下标i和j

扩展问题

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]也要快。

时间: 2024-11-01 09:12:23

在给定数组中,找出最先满足两个数的和等于给定数,输出这两个元素的下表的相关文章

数组中找出最小的K个数

题目 给出一个数组,找出K个最小的值 例如给出数组{5,2,4,3,1},给定K值3,则输出结果为{2,3,1} 程序 先给出第一个版本的程序 1 public static void printKNum(int[] source, int k) {//算法入口 2 if (k <= 0) { 3 System.out.println("请出入合法的K值"); 4 } else if (source.length <= k) {//如果数组的长度小于等于K,则全部输出 5

刷题之给定一个整数数组 nums 和一个目标值 taget,请你在该数组中找出和为目标值的那 两个 整数

今天下午,看了一会github,想刷个题呢,就翻出来了刷点题提高自己的实际中的解决问题的能力,在面试的过程中,我们发现,其实很多时候,面试官 给我们的题,其实也是有一定的随机性的,所以我们要多刷更多的题.去发现问题. 题目:     给定一个整数数组 nums 和一个目标值 taget,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标. 你可以假设每种输入只会对应一个答案.但是,你不能重复利用这个数组中同样的元素. 解析: 实际这里就是给你的一个列表的数字,给你一个预期,让你返

华为机试—给定字符串中找出单词

题目: 在给定字符串中找出单词("单词"由大写字母和小写字母字符构成,其他非字母字符视为单词的间隔,如空格.问号.数字等等:另外单个字母不算单词):找到单词后,按照长度进行降序排序,(排序时如果长度相同,则按出现的顺序进行排列),然后输出到一个新的字符串中:如果某个单词重复出现多次,则只输出一次:如果整个输入的字符串中没有找到单词,请输出空串.输出的单词之间使用一个"空格"隔开,最后一个单词后不加空格. 要求实现函数: void my_word(charinput[

C语言 选择排序算法原理和实现 从数组中 找出最小的元素然后交换位置

#include <stdio.h> int main(void) { /* 选择排序算法 原理:从数组中 找出最小的元素然后交换位置: */ int a[10] = {9,5,10,7,2,3,1,6,8,4}; int i=0,j=0; int n = sizeof(a)/4; //外循环n-1轮 for(i=0;i<n-1;i++){ int pos = i;//始终指向最小的位置 for(j=i+1;j<n;j++){ if(a[j]<a[pos]){ pos = j

C语言:对传入sp的字符进行统计,三组两个相连字母“ea”&quot;ou&quot;&quot;iu&quot;出现的次数,并将统计结果存入ct所指的数组中。-在数组中找出最小值,并与第一个元素交换位置。

//对传入sp的字符进行统计,三组两个相连字母“ea”"ou""iu"出现的次数,并将统计结果存入ct所指的数组中. 1 #include <stdio.h> 2 #include <string.h> 3 #pragma warning (disable:4996) 4 void fun(char*sp ,int *ct) 5 { 6 int a=0, b=0, c=0; 7 while (*sp != '\0') 8 { 9 if (*s

笔试题--在一个整数数组中找出第5大的数

/** * 在一个整数数组中找出第5大的数 * 思路是首先在数组中找到最小数,然后依次找到第五大的数 * * @param array * @return */ public static int[] selectionSort(int[] array) { if (array.length == 0) return array; for (int i = 0; i < array.length; i++) { int minIndex = i; for (int j = i; j < arr

面试题-10亿个数中找出最大的10000个数(top K问题)

一个较好的方法:先拿出10000个建立小根堆,对于剩下的元素,如果大于堆顶元素的值,删除堆顶元素,再进行插入操作,否则直接跳过,这样知道所有元素遍历完,堆中的10000个就是最大的10000个.时间复杂度: m + (n-1)logm = O(nlogm) 优化的方法:可以把所有10亿个数据分组存放,比如分别放在1000个文件中(如果是字符串hash(x)%M).对每个文件,建立大小为10000的小根堆,然后按有序数组的合并合并起来,取出最大的10000个即是答案. top K问题 在大规模数据

[面试题]在数组中找出3个数使得它们和为0

给定一个数组S,试找出3个数a, b, c,使得a+b+c=0.也即从集合中找出所有的和为0的3个数. 例如:集合S={-1,0, 1, 2, -1, 4},则满足条件的3个数有2对:(-1, 0, 1)和(-1, 2, -1).注意(-1,1,0)与(-1,0,1)算同一个解,所以不用重复考虑. 当然该例子集合的解也可以写成:(0, 1, -1)和(2, -1, -1). 参考了:http://blog.csdn.net/wangran51/article/details/8858398,他给

Leetcode34---&gt;Search for a Range(在排序数组中找出给定值出现的范围)

题目:给定一个排序数组,找出给定的target值出现的范围:算法复杂度要求在O(logn);如果没有找到,则返回[-1, -1]; 举例: For example,Given [5, 7, 7, 8, 8, 10] and target value 8,return [3, 4]. 解题思路: 一看到题目要求的时间复杂度O(logn),就自然想要要用到二分的方法,这道题目,我们自然也是用二分的方法: mid = (start + end) / 2;则target和nums[mid]的关系有三种: