编程之法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] 我们学到要保证在并发情况下对于共享资源的安全访问,就需要用到锁. 但是,加锁通常情况下会让运行效率 ...
随机推荐
- 给button增加下划线
如何给button增加下划线简单版 - (void)setUnderLineForButton:(UIButton *)btn withTitle:(NSString *)title{ //利用富 ...
- [笔记] Delphi 10.2.1 Tokyo 安装使用笔记
Android 平台: ListView 滑动速度已有改善,但比起 Berlin 还是略慢一些(在较慢的机子可感觉的到)仅于 Android 平台,其它平台没差. TMemo, TEdit 输入文字的 ...
- 记换换回收一个js逆向分析
随着现在对数据的重视程度越来越高,现在各大网站都加强了反爬技术,比如本文中js加密 url地址:https://www.huanhuanhuishou.com/gujia/22201.html 需要爬 ...
- Bugku Writeup —文件上传2(湖湘杯)
我们先来看下题目,题目说明是文件上传 我们可以尝试通过构造payload来进行测试 php://filter/read=convert.base64-encode/resource=flag 获取到f ...
- lua io操作(一)
最近在做可视化窗口数据配置 使用的lua 语言,免不了IO操作 通过查阅资料,做了如下总结,易于理解 lua里的文件读写模型来自C语言,分为完整模型(和C一样).简单模型. 1.简单模型 io.inp ...
- JavaWeb基础—过滤器Filter
一.概念 JavaWeb三大组件之一(组件都有一个特性,需要在web.xml中配置) 过滤器:会在一组资源(jsp servlet等)的前面执行,可以让请求得到目标资源,也可以终止请求,不再继续 也就 ...
- 对Dataguard的三种模式的理解
模式1:最大可保护模式: 必须同步. 模式2:最大可用性模式: 能同步就同步,不能同步就不同步. 模式3:最大性能模式: 异步模式.
- python模拟随机游走
在python中,可以利用数组操作来模拟随机游走. 下面是一个单一的200步随机游走的例子,从0开始,步长为1和-1,且以相等的概率出现.纯Python方式实现,使用了内建的 random 模块: # ...
- [C/C++11]_[初级]_[std::bind介绍和使用]
场景 1.C++11 引入了std::function 对象, 这个对象可以通过std::bind封装所有的函数, 并通过代理调用这个std::function的方式调用这个函数. 比如通过统一的方式 ...
- Kubernetes学习之路(九)之kubernetes命令式快速创建应用
1.使用命令kubectl run创建应用 语法: kubectl run NAME --image=image [--env="key=value"] [--port=port] ...