数组篇

2.2 求和为定值的两个数:

题目描述:有n个整数,找出其中满足两数相加为target的两个数(如果有多组满足,只需要找出其中一组),要求时间复杂度尽可能低。


解法一:

思路:开散列映射,空间换时间, 查找耗时o(n)

Writer: zzq

Function: 求和为定值的两个数。

方法一: 开散列映射(哈希表)。

1) 用哈希表Hashmap先把数组中的数字和对应的下标进行存储,(键,值)=(具体数值,对应下标);

2) 遍历数组,对loss=target-nums[i],在Hashmap中找是否存在loss,找到即返回loss所对应的value,也就是所对应的数组下标;

时间复杂度:O(n)



  1. #include<iostream>
  2. #include<map>
  3. using namespace std;
  4. //哈希表存储查找
  5. void twoSum(int *nums, int *result, int length, int target) {
  6. map<int, int> hashmap;
  7. for (int i = 0; i < length; i++)
  8. hashmap[nums[i]]=i;
  9. map<int, int>::iterator it;
  10. for (int i = 0; i < length; i++) {
  11. int v = target - nums[i];
  12. it = hashmap.find(v);
  13. if(it!=hashmap.end() && i != it->second){
  14. result[0] = i;
  15. result[1] = hashmap[v];
  16. break;
  17. }
  18. }
  19. }
  20. int main(){
  21. int nums[]={10,12,8,56,98,43,21,15,76,19};
  22. int target = 20;
  23. int result[2] = {0,0};
  24. twoSum(nums, result,10, target);
  25. cout<<result[0]<<' '<<result[1]<<endl;
  26. return 0;
  27. }

解法二:

思路:快排O(logn)+二分法O(nlogn).

Writer: zzq

Function: 求和为定值的两个数。

方法二: 1)先对给定数组进行排序;

2)在排序好的数组基础上,每次对于loss=target-nums[i],是用二分法查找loss是否存在,如果存在,则返回这两个数;

时间复杂度:O(logn)+O(nlogn),

【 排序:O(logn);

二分查找: O(nlogn)。



  1. #include<iostream>
  2. #include<algorithm>
  3. #include<stdio.h>
  4. using namespace std;
  5. // 快速排序
  6. void QuickSort(int *a, int begin, int end){
  7. if(begin<end){
  8. int i = begin;
  9. int j = end;
  10. int temp = *(a+i);
  11. while(i<j){
  12. while(i<j&&*(a+j)>=temp)j--;
  13. if(i<j){
  14. *(a+i)=*(a+j);
  15. i++;
  16. }
  17. while(i<j&&*(a+i)<=temp)i++;
  18. if(i<j){
  19. *(a+j)=*(a+i);
  20. j--;
  21. }
  22. }
  23. *(a+i)=temp;
  24. QuickSort(a,begin,i-1);
  25. QuickSort(a,i+1,end);
  26. }
  27. }
  28. //二分查找
  29. int BinaryQuery(int *a,int goal,int start, int end){
  30. int i=start,j=end;
  31. int flag = 0;
  32. while(i<=j){
  33. int middle = (j-i)/2;
  34. if(goal==*(a+middle)){
  35. return 1; // 找到目标值
  36. }
  37. else if(goal<*(a+middle)){ // 目标值在左半部分
  38. j = middle-1; // 尾下标指向左半部分最后一个元素
  39. }
  40. else{ // 目标值在右半部分
  41. i = middle +1; // 首指针指向右半部分最后一个元素
  42. }
  43. }
  44. return 0;
  45. }
  46. int main(){
  47. int n,sum;
  48. cin>>n>>sum;
  49. int a[n];
  50. int i;
  51. for(i = 0;i<n;i++)cin>>a[i];
  52. QuickSort(a,0,n-1); // 快排
  53. for(i = 0;i < n;i++){
  54. if((sum-a[i])>0){
  55. int flag = BinaryQuery(a,sum-a[i],0, n-1);
  56. if(flag){
  57. cout<<a[i]<<' '<<sum-a[i]<<endl;
  58. break;
  59. }
  60. }
  61. }
  62. return 0;
  63. }

解法三:

思路:快排O(logn)+ two pointers [首尾指针法]O(n).

Writer: zzq

Function: 求和为定值的两个数。

方法二: 1)先对给定数组进行排序;

2)在排序好的数组基础上,每次对于loss=target-nums[i],是用首尾指针法查找loss是否存在,如果存在,则返回这两个数;

时间复杂度:O(logn)+O(nlogn),

【 排序:O(logn);

two pointers: O(n)。


  1. #include<iostream>
  2. #include<algorithm>
  3. #include<stdio.h>
  4. using namespace std;
  5. // 快速排序
  6. void QuickSort(int *a, int begin, int end){
  7. if(begin<end){
  8. int i = begin;
  9. int j = end;
  10. int temp = *(a+i);
  11. while(i<j){
  12. while(i<j&&*(a+j)>=temp)j--;
  13. if(i<j){
  14. *(a+i)=*(a+j);
  15. i++;
  16. }
  17. while(i<j&&*(a+i)<=temp)i++;
  18. if(i<j){
  19. *(a+j)=*(a+i);
  20. j--;
  21. }
  22. }
  23. *(a+i)=temp;
  24. QuickSort(a,begin,i-1);
  25. QuickSort(a,i+1,end);
  26. }
  27. }
  28. // 首尾指针法
  29. void GetGoalIndex(int *a, int goal,int start,int end){
  30. int begin = start;
  31. int last = end;
  32. while(begin<=last){
  33. int currentSum = *(a+begin)+*(a+last);
  34. if(currentSum==goal){
  35. cout<<*(a+begin)<<' '<<*(a+last);
  36. // 如果需要找到所有满足条件的对数,则需要加上这两行
  37. //begin++;
  38. //last--;
  39. break;
  40. }
  41. else{
  42. if (currentSum>goal){
  43. last--;
  44. }
  45. else{
  46. begin++;
  47. }
  48. }
  49. }
  50. }
  51. int main(){
  52. int n,sum;
  53. cin>>n>>sum;
  54. int a[n];
  55. int i;
  56. for(i = 0;i<n;i++)cin>>a[i];
  57. QuickSort(a,0,n-1); // 快排
  58. GetGoalIndex(a,sum,0, n-1);
  59. return 0;
  60. }

举一反三:

找和为定值的两个数的下标,并且两个数不能是同一个。

1:散列表法

2:快排+two pointers(新建数组b跟踪存储下标变化情况)。

  1. void QuickSort(int *a, int *b, int begin, int end){
  2. //cout<<begin<<' '<<end<<endl;
  3. if(begin<end){
  4. int i = begin;
  5. int j = end;
  6. int temp = *(a+i);
  7. int temp_index=*(b+i);
  8. while(i<j){
  9. while(i<j&&*(a+j)>=temp)j--;
  10. if(i<j){
  11. *(a+i)=*(a+j);
  12. *(b+i)=*(b+j);
  13. i++;
  14. }
  15. while(i<j&&*(a+i)<=temp)i++;
  16. if(i<j){
  17. *(a+j)=*(a+i);
  18. *(b+j)=*(b+i);
  19. j--;
  20. }
  21. }
  22. *(a+i)=temp;
  23. *(b+i)=temp_index;
  24. //for(int i=0;i<10;i++)cout<<b[i]<<' ';
  25. //cout<<endl;
  26. QuickSort(a, b, begin, i-1);
  27. QuickSort(a, b, i+1, end);
  28. }
  29. }
  30. // 寻找下标 ,用数组c接收下标
  31. void GetGoalIndex(int *a, int *b, int *c, int goal,int start,int end){
  32. int begin = start;
  33. int last = end;
  34. while(begin<=last){
  35. int currentSum = *(a+begin)+*(a+last);
  36. if(currentSum==goal){
  37. if(*(b+begin)>*(b+last)){
  38. *c=*(b+last);
  39. *(c+1)=*(b+begin);
  40. }
  41. else{
  42. *c=*(b+begin);
  43. *(c+1)=*(b+last);
  44. }
  45. break;
  46. }
  47. else{
  48. if (currentSum>goal){
  49. last--;
  50. }
  51. else{
  52. begin++;
  53. }
  54. }
  55. }
  56. }
  57. int* twoSum(int* nums, int numsSize, int target) {
  58. int i;
  59. int b[numsSize];
  60. static int c[2];
  61. for(i = 0;i<numsSize;i++){
  62. b[i]=i;
  63. }
  64. QuickSort(nums, b, 0, numsSize-1);
  65. //for(int i=0;i<10;i++)cout<<b[i]<<' ';
  66. //cout<<endl;
  67. GetGoalIndex(nums, b, c,target, 0, numsSize-1);
  68. return c;
  69. }

编程之法section II: 2.2 和为定值的两个数的更多相关文章

  1. 编程之法section II: 2.1 求最小的k个数

    ====数组篇==== 2.1 求最小的k个数: 题目描述:有n个整数,请找出其中最小的k个数,要求时间复杂度尽可能低. 解法一: 思路:快排后输出前k个元素,O(nlogn). writer: zz ...

  2. 编程之法:面试和算法心得(寻找最小的k个数)

    内容全部来自编程之法:面试和算法心得一书,实现是自己写的使用的是java 题目描述 输入n个整数,输出其中最小的k个. 分析与解法 解法一 要求一个序列中最小的k个数,按照惯有的思维方式,则是先对这个 ...

  3. 编程之法:面试和算法心得(字符串包含java实现)

    内容全部来自编程之法:面试和算法心得一书,实现是自己写的使用的是java 题目描述 给定两个分别由字母组成的字符串A和字符串B,字符串B的长度比字符串A短.请问,如何最快地判断字符串B中所有字母是否都 ...

  4. 编程之法:面试和算法心得(旋转字符串java实现)

    内容全部来自编程之法:面试和算法心得一书,实现是自己写的使用的是java 题目描述 给定一个字符串,要求把字符串前面的若干个字符移动到字符串的尾部,如把字符串“abcdef”前面的2个字符'a'和'b ...

  5. 老雷socket编程之websocket实现

    老雷socket编程之websocket实现 我们主要实现私聊和群聊两个功能,要在web端实现想微信QQ那样的即时通讯的功能,我们需要了解一下websocket.websocket是一种可以双向通讯的 ...

  6. Java并发编程之CAS第三篇-CAS的缺点及解决办法

    Java并发编程之CAS第三篇-CAS的缺点 通过前两篇的文章介绍,我们知道了CAS是什么以及查看源码了解CAS原理.那么在多线程并发环境中,的缺点是什么呢?这篇文章我们就来讨论讨论 本篇是<凯 ...

  7. C++混合编程之idlcpp教程Lua篇(7)

    上一篇在这 C++混合编程之idlcpp教程Lua篇(6) 第一篇在这 C++混合编程之idlcpp教程(一) 与LuaTutorial4工程相似,工程LuaTutorial5中,同样加入了四个文件: ...

  8. shell编程之awk命令详解

    shell编程之awk命令详解 a:focus { outline: thin dotted #333; outline: 5px auto -webkit-focus-ring-color; out ...

  9. 并发编程之:ThreadLocal

    大家好,我是小黑,一个在互联网苟且偷生的农民工. 从前上一期[并发编程之:synchronized] 我们学到要保证在并发情况下对于共享资源的安全访问,就需要用到锁. 但是,加锁通常情况下会让运行效率 ...

随机推荐

  1. HTML5新增的几个容器模块

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. ThinkPHP5.1中数据查询使用field方法数组参数起别名时遇到的问题

    首先数据库基本查询是没有问题的 <?php namespace app\index\controller; use think\Db; class Demo5 { //1.单条查询 public ...

  3. Cannot obtain block length for LocatedBlock故障分析和解决

    来源:CSDN 作者:Syn良子 原文:https://blog.csdn.net/cssdongl/article/details/77750495  一.问题背景 问题产生的原因可能是由于前几日H ...

  4. 链接SQLServer数据库 导出csv文件

    依赖::::<dependency> <groupId>com.microsoft.sqlserver</groupId> <artifactId>ms ...

  5. 用NI的数据采集卡实现简单电子测试之6——数字I/O及测试平台

    本文从本人的163博客搬迁至此. 前面几个例子介绍了NI数据采集卡的模拟输入和输出功能,本例则集中介绍USB-6009的数字输入输出功能.本例包括基本数字IO电路及在LabVIEW中控制USB-600 ...

  6. 20155339 《信息安全系统设计》第十周课下作业-IPC

    20155339 <信息安全系统设计>第十周课下作业-IPC 共享内存 共享内存是在多个进程之间共享内存区域的一种进程间的通信方式,由IPC为进程创建的一个特殊地址范围,它将出现在该进程的 ...

  7. BSGS算法总结

    BSGS算法总结 \(BSGS\)算法(Baby Step Giant Step),即大步小步算法,用于解决这样一个问题: 求\(y^x\equiv z\ (mod\ p)\)的最小正整数解. 前提条 ...

  8. VC编译连接选项详解

    VC编译连接选项详解 大家可能一直在用VC开发软件,但是对于这个编译器却未必很了解.原因是多方面的.大多数情况下,我们只停留在“使用”它,而不会想去“了解”它.因为它只是一个工具,我们宁可把更多的精力 ...

  9. Python_sklearn机器学习库学习笔记(六) dimensionality-reduction-with-pca

    # 用PCA降维 #计算协方差矩阵 import numpy as np X=[[2,0,-1.4], [2.2,0.2,-1.5], [2.4,0.1,-1], [1.9,0,-1.2]] np.c ...

  10. Lookup 转换组件

    查找转换(Lookup)组件用于实现两个数据源的连接,实现的方式是嵌套循环.查找转换通常在内存中缓存查找数据集,然后在输入管道中,把输入数据的每一行都和缓存中的查找数据集进行比较,并输出匹配成功和失败 ...