在数组中找几个数的和等于某个数[LeetCode]
首先明确一点,这个方面的问题设计到的知识点是数组的查找的问题。对于类似的这样的查找操作的具体办法就是三种解决方法:
1.暴力算法,多个for循环,很高的时间复杂度
2.先排序,然后左右夹逼,但是这样会破坏原始数组的下表
3.利用Hash表,直接定位元素,很少的时间复杂度
TwoSum
先来看看最简单的,在一个数组中找两个数的和等于某个数。
这个题目最简简单的方法就是暴力法,所需的时间复杂度是O(n2),但是这是不允许的,所以一个O(n)的方法就是利用Hash表存储数据,这样能够把查找的时间降低下来。使用到的工具就是unordered_map。在这个hash表中,key是数组的数字本身,value是数组数字的下标值。这样只需要把原数组扫描一遍,对于每一个数组中的值,求target与数组元素的差值,然后把这个差值作为key到hash表中找对应的value。
但是注意这样的值:
3 2 4 target=6
这样会产生三组值满足:(3,3)(2,4)(4,2)所以要规定一下:第二个通过hash得到的下标值一定要比第一个下标值大才可以。
vector<int> twoSum(vector<int>& nums, int target)
{
unordered_map<int, int> mapping;
vector<int> result; for(int i = 0; i < nums.size(); i++)
{
mapping[nums[i]] = i;
} for(int i = 0; i < nums.size(); i++)
{
const int gap = target - nums[i]; if(mapping.find(gap) != mapping.end() && mapping[gap] > i)
{
result.push_back(i + 1);
result.push_back(mapping[gap] + 1);
}
} return result;
}
find函数,在找到的时候会返回一个指向该元素的iterator,如果没有找到会返回一个end。如果找到了,可以通过operator[]来访问这个元素。
对于2-sum的算法,暴力算法的时间复杂度是O(n2),Hash表的时间复杂度是O(n),排序然后两边夹逼的时间复杂度是排序的时间复杂度加上左右夹逼的时间复杂度:O(NlogN)+O(N)=O(NlogN)。
ThreeSum
对于三个数的和问题,暴力的算法就是使用三个for循环,这样的话时间复杂度是O(n3),所以一个好的改进就是先对原始的数组排序,然后使用两边夹逼的方法。但是要注意一些细节的问题:
1.具体的实现方法是,先固定一个,然后就成了2Sums的两边夹逼方法。
2.原始的数组是允许重复的,但是得到的solution是不允许重复的,所以要做一些合理的去重处理。防止-1,-1,-1,2,2这样的数组会得到-1,-1,2和-1,-1,2两组一样的结果。
vector<vector<int> > threeSum(vector<int>& nums, int target)
{
vector<vector<int> > result; if(nums.size() < 3)
return result; for(int i = 0; i < nums.size() - 2; i++)
{
int j = i + 1;
int k = nums.size() - 1; if(i > 0 && nums[i] == nums[i-1])
continue; while(j < k)
{
int sum = nums[i] + nums[j] + nums[k];
if(sum < target)
{
j++;
}
else if(sum > target)
{
k--;
}
else
{
vector<int> temp;
temp.push_back(nums[i]);
temp.push_back(nums[j]);
temp.push_back(nums[k]); result.push_back(temp);
j++;
k--; //去重,防止最后的结果有重复的三元组
while(nums[j] == nums[j-1] && nums[k] == nums[k+1] && j < k)
{
j++;
}
}
}//while
}//for return result;
}
算法的时间复杂度是O(NlogN)+O(N2),所以总的时间复杂度是O(N2)。
ThreeSumClosest
再看一个很类似的题目:找最接近给定值的那三个数,并输出这三个数的和。
用的方法仍然是先排序,然后利用两边夹逼的方法。
int threeSumClosest(vector<int>& nums, int target)
{
int min_gap = 65535;
int result; sort(nums.begin(), nums.end()); for(int i = 0; i < nums.size() - 2; i++)
{
int k = nums.size() - 1;
int j = i + 1; while(j < k)
{
int sum = nums[i] + nums[j] + nums[k];
int gap = abs(sum - target); if(gap < min_gap)
{
result = sum;
min_gap = gap;
} if(sum < target)
{
j++;
}
else
{
k--;
} }//while
}//for return result;
}
FourSum
这个问题还是延续前面的那种方法,先排序,然后利用左右夹逼。这样的话排序的时间复杂度是O(NlogN),左右夹逼的时间复杂度是O(N3),所以总的时间复杂度是O(N3)。但是这个FourSum比其他的难点在于:要仔细的对待去重的问题,不然会得到很多重复一样的答案。
vector<vector<int> > fourSum(vector<int>& nums, int target)
{ vector<vector<int> > result;
if(nums.size() < 4)
return result; sort(nums.begin(), nums.end()); for(int i = 0; i < nums.size() - 3; i++)
{
if(i > 0 && nums[i] == nums[i-1])
continue; for(int j = i + 1; j < nums.size() - 2; j++)
{
if(j > 1 && nums[j] == nums[j - 1])
continue; int l = j + 1;
int k = nums.size() - 1; while(l < k)
{
int sum = nums[i] + nums[j] + nums[l] + nums[k];
if(sum < target)
{
l++;
}
else if(sum > target)
{
k--;
}
else
{
vector<int> tmp;
tmp.push_back(nums[i]);
tmp.push_back(nums[j]);
tmp.push_back(nums[l]);
tmp.push_back(nums[k]); result.push_back(tmp);
l++;
k--; while(nums[l]==nums[l-1]&&nums[k]==nums[k+1]&&l<k)
l++;
}
}//while }//for
}//for
}
对于4-sum的算法其实可以用hash表做一个优化,就是先用hash表存元数组中的任意两个元素的和,然后在对这个新的hash使用2-sum的线性查询,所以总的时间复杂度是O(N2)。具体的算法分析这里分享一个连接:
烟客旅人:http://tech-wonderland.net/blog/summary-of-ksum-problems.html
在数组中找几个数的和等于某个数[LeetCode]的更多相关文章
- 3sum(从数组中找出三个数的和为0)
Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all un ...
- 用C#写一个函数,在一个数组中找出随意几个值相加等于一个值 与迭代器对比
算法!用C#写一个函数,在一个数组中找出随意几个值相加等于一个值比如,数组{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20} 要找出那些数相加等 ...
- Leetcode33--->Search in Rotated Sorted Array(在旋转数组中找出给定的target值的位置)
题目: 给定一个旋转数组,但是你不知道旋转位置,在旋转数组中找出给定target值出现的位置:你可以假设在数组中没有重复值出现 举例: (i.e., 0 1 2 4 5 6 7 might becom ...
- 刷题之给定一个整数数组 nums 和一个目标值 taget,请你在该数组中找出和为目标值的那 两个 整数
今天下午,看了一会github,想刷个题呢,就翻出来了刷点题提高自己的实际中的解决问题的能力,在面试的过程中,我们发现,其实很多时候,面试官 给我们的题,其实也是有一定的随机性的,所以我们要多刷更多的 ...
- C语言 选择排序算法原理和实现 从数组中 找出最小的元素然后交换位置
#include <stdio.h> int main(void) { /* 选择排序算法 原理:从数组中 找出最小的元素然后交换位置: */ int a[10] = {9,5,10,7, ...
- 从数组中找出所有组合为s的数
java版本 package numCombine; /** * 从数组中找出所有组合为s的数 * @author root * */ public class NumComberAll { publ ...
- C语言:对传入sp的字符进行统计,三组两个相连字母“ea”"ou""iu"出现的次数,并将统计结果存入ct所指的数组中。-在数组中找出最小值,并与第一个元素交换位置。
//对传入sp的字符进行统计,三组两个相连字母“ea”"ou""iu"出现的次数,并将统计结果存入ct所指的数组中. #include <stdio.h& ...
- 数组中找出最小的K个数
题目 给出一个数组,找出K个最小的值 例如给出数组{5,2,4,3,1},给定K值3,则输出结果为{2,3,1} 程序 先给出第一个版本的程序 public static void printKNum ...
- 如何求出数组中最小(或者最大)的k个数(least k问题)
输入n个整数,如何求出其中最小的k个数? 解法1. 当然最直观的思路是将数组排序,然后就可以找出其中最小的k个数了,时间复杂度以快速排序为例,是O(nlogn): 解法2. 借助划分(Partitio ...
随机推荐
- 看大数据时代下的IT架构(1)业界消息队列对比
一.MQ(Message Queue) 即 消息队列,一般用于应用系统解耦.消息异步分发,能够提高系统吞吐量.MQ的产品有很多,有开源的,也有闭源,比如ZeroMQ.RabbitMQ. ActiveM ...
- Codechef Nuclear Reactors 题解
There are K nuclear reactor chambers labelled from 0 to K-1. Particles are bombarded onto chamber 0. ...
- IOS开发环境更换后重新制作Provisioning Profile证书详解
新换了台Macbook,又折腾了一遍Provisioning Profile证书,苹果的证书繁锁复杂,每次制作都相当麻烦,而且Provisioning Profile证书是与设备绑定的,所以更换开发环 ...
- vs2010调试快捷键
VS2010单步调试 1.设置断点 F9设置或者取消断点,如果当前行未设置断点,则F9可以再当前行设置断点,如果已经设置,则为去除断点 2.单步调试 F10不进入函数单步,F11进入函数单步 , ...
- Java中使用Observer接口和Observable类实践Observer观察者模式
在Java中通过Observable类和Observer接口实现了观察者模式.实现Observer接口的对象是观察者,继承Observable的对象是被观察者. 1. 实现观察者模式 实现观察者模式非 ...
- vs 2005 在IE下断点不起作用
vs2005 加断点调试,ie下不起作用. 1. 点击[开始]->[运行] 命令:regedit. 2. 定位到HKEY_LOCALMACHINE -> SOFTWARE -> Mi ...
- 升级python的sqlite库版本
今天了解了一下用python获取chrome cookie信息,在研究的过程中,发现打开数据库失败,后来调查了一下发现是由于sqlite3库太老的缘故,起码需要3.8以上,然后看了一下python 2 ...
- Asp.Net请求处理机制中IsApiRuntime解析
今天看了web请求的生命周期,看完了还有些不懂,就是用反编译工具,查看封装内库的内部实现. 从计算机内部查到web.dll,使用反编译工具打开 打开后 public int ProcessReques ...
- javaTemplates-学习笔记二
配置PlayFramework环境 下载jar包[Play with Activator],这一步有点晕是JAVA程序员CMD执行的步骤;运行了jar包下载了很多配置文件什么的,有的资源没有VPN链接 ...
- 《JavaScript+DOM编程艺术》的摘要(二)---DOM中的几个方法
//DOM: //对象是一种独立的数据集合,与某个特定对象相关联的变量被称为这个对象的属性,通过某个特定对象可以为之调用的函数被称为这个对象的方法 // //4个非常实用的DOM方法: //检索特定元 ...