编程之法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] 我们学到要保证在并发情况下对于共享资源的安全访问,就需要用到锁. 但是,加锁通常情况下会让运行效率 ...
随机推荐
- iOS 多线程:『RunLoop』详尽总结
1. RunLoop 简介 1.1 什么是 RunLoop? 可以理解为字面意思:Run 表示运行,Loop 表示循环.结合在一起就是运行的循环的意思.哈哈,我更愿意翻译为『跑圈』.直观理解就像是不停 ...
- java常用API之Date类
Date类: 类 Date 表示特定的瞬间,精确到毫秒. 毫秒概念:1000毫秒=1秒 毫秒的0点: System.currentTimeMillis() 返回值long类型参数 用于获取当前日 ...
- HTML5 新增内容
1. 新增标签 音频 <audio> <source src=""/> </audio> 视频 <video> <source ...
- WPF DataGrid 样式分享
原文:WPF DataGrid 样式分享 隔行换色,鼠标单击,悬浮样式都有 先看效果: 代码: <DataGrid AutoGenerateColumns="False" N ...
- 对ThreadLocal的源码解读
早在JDK 1.2的版本中就提供Java.lang.ThreadLocal,ThreadLocal为解决多线程程序的并发问题提供了一种新的思路.使用这个工具类可以很简洁地编写出优美的多线程程序. 功能 ...
- 菜鸟vimer成长记——第3章、文件
上一章一直在讲的是vim的文本的操作,本章主要讲的是vim的文件操作. 本章的有些概念和传统的文本编辑器也不尽相同.所以需要注意概念或者切切说是思维习惯的区别. vim 允许在一个编辑会话中编辑多个文 ...
- 不把DB放进容器的理由
原文地址:http://www.tuicool.com/articles/6VbqeqQ 原文为英文,以下是笔者的个人总结. 此处的DB包括但不限于Redis.ElasticSearch. 1.数据安 ...
- 角色和武器Shader特效开发
角色Shader的动效需求 角Shader的开发不知要实现最基础光照等功能, 可能还要在角色武器的Shader增加多种动效, 比如因武器品质区分的流光特效, 被技能击中时的冻结效果. 这类动效的实现方 ...
- 使用CNN做数字识别和人脸识别
上次写的一层神经网络也都贴这里了. 我有点困,我先睡觉,完了我再修改 这个代码写法不太符合工业代码的规范,仅仅是用来学习的的.还望各位见谅 import sys,ossys.path.append(o ...
- Java字符串连接操作的性能问题
首先,看一段实验程序: package com.test; class StringTest { public static void main(String[] args) { long start ...