编程之法section II: 2.2 和为定值的两个数
数组篇
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 和为定值的两个数的更多相关文章
- 编程之法section II: 2.1 求最小的k个数
====数组篇==== 2.1 求最小的k个数: 题目描述:有n个整数,请找出其中最小的k个数,要求时间复杂度尽可能低. 解法一: 思路:快排后输出前k个元素,O(nlogn). writer: zz ...
- 编程之法:面试和算法心得(寻找最小的k个数)
内容全部来自编程之法:面试和算法心得一书,实现是自己写的使用的是java 题目描述 输入n个整数,输出其中最小的k个. 分析与解法 解法一 要求一个序列中最小的k个数,按照惯有的思维方式,则是先对这个 ...
- 编程之法:面试和算法心得(字符串包含java实现)
内容全部来自编程之法:面试和算法心得一书,实现是自己写的使用的是java 题目描述 给定两个分别由字母组成的字符串A和字符串B,字符串B的长度比字符串A短.请问,如何最快地判断字符串B中所有字母是否都 ...
- 编程之法:面试和算法心得(旋转字符串java实现)
内容全部来自编程之法:面试和算法心得一书,实现是自己写的使用的是java 题目描述 给定一个字符串,要求把字符串前面的若干个字符移动到字符串的尾部,如把字符串“abcdef”前面的2个字符'a'和'b ...
- 老雷socket编程之websocket实现
老雷socket编程之websocket实现 我们主要实现私聊和群聊两个功能,要在web端实现想微信QQ那样的即时通讯的功能,我们需要了解一下websocket.websocket是一种可以双向通讯的 ...
- Java并发编程之CAS第三篇-CAS的缺点及解决办法
Java并发编程之CAS第三篇-CAS的缺点 通过前两篇的文章介绍,我们知道了CAS是什么以及查看源码了解CAS原理.那么在多线程并发环境中,的缺点是什么呢?这篇文章我们就来讨论讨论 本篇是<凯 ...
- C++混合编程之idlcpp教程Lua篇(7)
上一篇在这 C++混合编程之idlcpp教程Lua篇(6) 第一篇在这 C++混合编程之idlcpp教程(一) 与LuaTutorial4工程相似,工程LuaTutorial5中,同样加入了四个文件: ...
- shell编程之awk命令详解
shell编程之awk命令详解 a:focus { outline: thin dotted #333; outline: 5px auto -webkit-focus-ring-color; out ...
- 并发编程之:ThreadLocal
大家好,我是小黑,一个在互联网苟且偷生的农民工. 从前上一期[并发编程之:synchronized] 我们学到要保证在并发情况下对于共享资源的安全访问,就需要用到锁. 但是,加锁通常情况下会让运行效率 ...
随机推荐
- 5.Control flow statements-流程控制(Dart中文文档)
你可以使用如下流程控制符: if and else for loops while and do-while loops break and continue switch and case asse ...
- linux下使用shell脚本获取终端宽度
获取终端大小时候的学习 学习日期:2018/11/3 问题来源: 在写shell脚本时想输出一行占满整个终端屏幕宽度的 横杠 发现for循环会导致执行缓慢 解决方法: 使用yes 命令 sed '50 ...
- 信息安全铁人三项赛--资质赛writeup
[博客目录] 工具 Burp Suite stegsolve.jar 十六进制编辑器 赛题 第一题 第二题 第三题 第四题 第五题 第六题 1- 工具: 1.1- Burp Suite 一款可以进行再 ...
- 20155327预备作业3:Linux安装及命令入门
20155327预备作业3:Linux安装及命令入门 安装Linux操作系统 由于之前安装过所以这里就不再赘述了 掌握Linux命令的学习方法 学习路径: 常用Ubuntu快捷键: CTRL+ALT+ ...
- mfc 动态分配内存
动态内存分配new 为数组动态分配内存 为多维数组分配内存 释放内存delete malloc free 动态内存分配new int * pi; pi= new int ; 为 ...
- Django中表单的用法深探
[转载说明:原文排版不是很好,为方便阅读,改进了排版] django的表单设计真的很棒,涉及非常多的功能,今天介绍django较为主流的几种表单使用方法.注:本文中表单与form通用.模型与model ...
- 基于Keras的imdb数据集电影评论情感二分类
IMDB数据集下载速度慢,可以在我的repo库中找到下载,下载后放到~/.keras/datasets/目录下,即可正常运行.)中找到下载,下载后放到~/.keras/datasets/目录下,即可正 ...
- 【RedHat Linux】 链路聚合
[链路聚合] RHEL 7运行模式:teamd 守护进程, teamdctlroundrobin 轮询activebackup 热备份, 其中一个位为backuploadbalance 负载均衡lac ...
- 处于同一域中的两台SQL Server 实例无法连接
处于同一个域中的两台Sql server 实例无法连接,报的错误信息如下: A network-related or instance-specific error occurred while es ...
- Post请求和Get请求;@RequestBody和@RequestParam
1.@RequestBody用于Post请求,接收json数据,例如:@RequestBody User user 例如:@RequestBody Map map .不要用于Get请求. 2.@Req ...