数组篇

2.2 求和为定值的两个数:

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


解法一:

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

Writer: zzq

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

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

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

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

时间复杂度:O(n)



#include<iostream>
#include<map>
using namespace std; //哈希表存储查找
void twoSum(int *nums, int *result, int length, int target) {
map<int, int> hashmap;
for (int i = 0; i < length; i++)
hashmap[nums[i]]=i;
map<int, int>::iterator it;
for (int i = 0; i < length; i++) {
int v = target - nums[i];
it = hashmap.find(v);
if(it!=hashmap.end() && i != it->second){
result[0] = i;
result[1] = hashmap[v];
break;
}
}
}
int main(){
int nums[]={10,12,8,56,98,43,21,15,76,19};
int target = 20;
int result[2] = {0,0};
twoSum(nums, result,10, target);
cout<<result[0]<<' '<<result[1]<<endl;
return 0;
}

解法二:

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

Writer: zzq

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

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

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

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

【 排序:O(logn);

二分查找: O(nlogn)。



#include<iostream>
#include<algorithm>
#include<stdio.h>
using namespace std;
// 快速排序
void QuickSort(int *a, int begin, int end){
if(begin<end){
int i = begin;
int j = end;
int temp = *(a+i);
while(i<j){
while(i<j&&*(a+j)>=temp)j--;
if(i<j){
*(a+i)=*(a+j);
i++;
}
while(i<j&&*(a+i)<=temp)i++;
if(i<j){
*(a+j)=*(a+i);
j--;
}
}
*(a+i)=temp; QuickSort(a,begin,i-1);
QuickSort(a,i+1,end);
}
} //二分查找
int BinaryQuery(int *a,int goal,int start, int end){
int i=start,j=end;
int flag = 0;
while(i<=j){
int middle = (j-i)/2;
if(goal==*(a+middle)){
return 1; // 找到目标值
}
else if(goal<*(a+middle)){ // 目标值在左半部分
j = middle-1; // 尾下标指向左半部分最后一个元素
}
else{ // 目标值在右半部分
i = middle +1; // 首指针指向右半部分最后一个元素
}
}
return 0;
}
int main(){
int n,sum;
cin>>n>>sum;
int a[n];
int i;
for(i = 0;i<n;i++)cin>>a[i]; QuickSort(a,0,n-1); // 快排 for(i = 0;i < n;i++){
if((sum-a[i])>0){
int flag = BinaryQuery(a,sum-a[i],0, n-1);
if(flag){
cout<<a[i]<<' '<<sum-a[i]<<endl;
break;
}
}
}
return 0;
}

解法三:

思路:快排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)。




#include<iostream>
#include<algorithm>
#include<stdio.h>
using namespace std;
// 快速排序
void QuickSort(int *a, int begin, int end){
if(begin<end){
int i = begin;
int j = end;
int temp = *(a+i);
while(i<j){
while(i<j&&*(a+j)>=temp)j--;
if(i<j){
*(a+i)=*(a+j);
i++;
}
while(i<j&&*(a+i)<=temp)i++;
if(i<j){
*(a+j)=*(a+i);
j--;
}
}
*(a+i)=temp; QuickSort(a,begin,i-1);
QuickSort(a,i+1,end);
}
}
// 首尾指针法
void GetGoalIndex(int *a, int goal,int start,int end){
int begin = start;
int last = end; while(begin<=last){
int currentSum = *(a+begin)+*(a+last);
if(currentSum==goal){
cout<<*(a+begin)<<' '<<*(a+last);
// 如果需要找到所有满足条件的对数,则需要加上这两行
//begin++;
//last--;
break; }
else{
if (currentSum>goal){
last--;
}
else{
begin++;
}
}
}
}
int main(){
int n,sum;
cin>>n>>sum;
int a[n];
int i;
for(i = 0;i<n;i++)cin>>a[i]; QuickSort(a,0,n-1); // 快排
GetGoalIndex(a,sum,0, n-1);
return 0;
}

举一反三:

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

1:散列表法

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

void QuickSort(int *a, int *b, int begin, int end){
//cout<<begin<<' '<<end<<endl;
if(begin<end){
int i = begin;
int j = end;
int temp = *(a+i);
int temp_index=*(b+i);
while(i<j){
while(i<j&&*(a+j)>=temp)j--;
if(i<j){
*(a+i)=*(a+j);
*(b+i)=*(b+j);
i++;
}
while(i<j&&*(a+i)<=temp)i++;
if(i<j){
*(a+j)=*(a+i);
*(b+j)=*(b+i);
j--;
}
}
*(a+i)=temp;
*(b+i)=temp_index;
//for(int i=0;i<10;i++)cout<<b[i]<<' ';
//cout<<endl;
QuickSort(a, b, begin, i-1);
QuickSort(a, b, i+1, end);
}
}
// 寻找下标 ,用数组c接收下标
void GetGoalIndex(int *a, int *b, int *c, int goal,int start,int end){
int begin = start;
int last = end;
while(begin<=last){
int currentSum = *(a+begin)+*(a+last);
if(currentSum==goal){
if(*(b+begin)>*(b+last)){
*c=*(b+last);
*(c+1)=*(b+begin);
}
else{
*c=*(b+begin);
*(c+1)=*(b+last);
}
break;
}
else{
if (currentSum>goal){
last--;
}
else{
begin++;
}
}
}
}
int* twoSum(int* nums, int numsSize, int target) {
int i;
int b[numsSize];
static int c[2];
for(i = 0;i<numsSize;i++){
b[i]=i;
} QuickSort(nums, b, 0, numsSize-1);
//for(int i=0;i<10;i++)cout<<b[i]<<' ';
//cout<<endl;
GetGoalIndex(nums, b, c,target, 0, numsSize-1);
return c;
}

编程之法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. linux 虚拟机 磁盘空间压缩

    /usr/bin/vmware-toolbox-cmd disk list /usr/bin/vmware-toolbox-cmd disk shrink / init 0

  2. flink 常见问题整理

    1. xml-apis 冲突问题 javax.xml.parsers.FactoryConfigurationError: Provider for class javax.xml.parsers.D ...

  3. Python学习之迭代器和生成器

    那么首先什么是迭代器和生成器呢? 迭代器即迭代的工具,那么什么又是迭代呢?所谓迭代:迭代是一个重复的过程,每次重读即一次迭代,并且每次迭代的结果都是下一次迭代的初始值.例: l=[1,2,3] cou ...

  4. inux下进程的最大线程数、进程最大数、进程打开的文件数

    inux下进程的最大线程数.进程最大数.进程打开的文件数 2008-12-07 23:48 =========================    如下转载自这里. linux 系统中单个进程的最大 ...

  5. 【转载】COM 组件设计与应用(十六)——连接点(vc.net)

    原文:http://vckbase.com/index.php/wv/1257.html 一.前言 上回书介绍了回调接口,在此基础上,我们理解连接点就容易多了. 二.原理 图一.连接点组件原理图.左侧 ...

  6. 【转载】MSXML应用总结 概念篇

    原文:http://blog.sina.com.cn/s/blog_48f93b530100e9tr.html 微软提供了大量的XML开发工具和技术,而SMXML(Microsoft XML Core ...

  7. 9 README,全套代码

    BBS+ BLOG系统(仿博客园) 一.概要 欢迎您使用该BBS+BLOG系统,希望在您使用的过程中体验到便捷和愉快的使用感受,并对我们的软件提出您发现的问题和建议,谢谢. 联系邮箱:liangshu ...

  8. 1 nodejs

      重点 :  

  9. 洛咕P3250 [HNOI2016]网络 整体二分

    这题太神仙了必须写博客... 显然可以想到二分答案.二分一个答案mid,如果所有长度\(\geq mid\)的路径都过x,那么答案一定\(<mid\),否则答案\(\geq mid\). 那么就 ...

  10. P1402 酒店之王

    P1402 酒店之王 每个人要匹配一个A和一个B,所以这样连边: S向每个房间连边. 每个房间向喜欢这个房间的人连边. 每个人向喜欢的菜连边. 每道菜向T连边. 边权均为1. 注意人要限流. // I ...