首先明确一点,这个方面的问题设计到的知识点是数组的查找的问题。对于类似的这样的查找操作的具体办法就是三种解决方法:

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]的更多相关文章

  1. 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 ...

  2. 用C#写一个函数,在一个数组中找出随意几个值相加等于一个值 与迭代器对比

    算法!用C#写一个函数,在一个数组中找出随意几个值相加等于一个值比如,数组{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20}  要找出那些数相加等 ...

  3. Leetcode33--->Search in Rotated Sorted Array(在旋转数组中找出给定的target值的位置)

    题目: 给定一个旋转数组,但是你不知道旋转位置,在旋转数组中找出给定target值出现的位置:你可以假设在数组中没有重复值出现 举例: (i.e., 0 1 2 4 5 6 7 might becom ...

  4. 刷题之给定一个整数数组 nums 和一个目标值 taget,请你在该数组中找出和为目标值的那 两个 整数

    今天下午,看了一会github,想刷个题呢,就翻出来了刷点题提高自己的实际中的解决问题的能力,在面试的过程中,我们发现,其实很多时候,面试官 给我们的题,其实也是有一定的随机性的,所以我们要多刷更多的 ...

  5. C语言 选择排序算法原理和实现 从数组中 找出最小的元素然后交换位置

    #include <stdio.h> int main(void) { /* 选择排序算法 原理:从数组中 找出最小的元素然后交换位置: */ int a[10] = {9,5,10,7, ...

  6. 从数组中找出所有组合为s的数

    java版本 package numCombine; /** * 从数组中找出所有组合为s的数 * @author root * */ public class NumComberAll { publ ...

  7. C语言:对传入sp的字符进行统计,三组两个相连字母“ea”"ou""iu"出现的次数,并将统计结果存入ct所指的数组中。-在数组中找出最小值,并与第一个元素交换位置。

    //对传入sp的字符进行统计,三组两个相连字母“ea”"ou""iu"出现的次数,并将统计结果存入ct所指的数组中. #include <stdio.h& ...

  8. 数组中找出最小的K个数

    题目 给出一个数组,找出K个最小的值 例如给出数组{5,2,4,3,1},给定K值3,则输出结果为{2,3,1} 程序 先给出第一个版本的程序 public static void printKNum ...

  9. 如何求出数组中最小(或者最大)的k个数(least k问题)

    输入n个整数,如何求出其中最小的k个数? 解法1. 当然最直观的思路是将数组排序,然后就可以找出其中最小的k个数了,时间复杂度以快速排序为例,是O(nlogn): 解法2. 借助划分(Partitio ...

随机推荐

  1. XCode破解真机调试

    XCode破解真机调试  3.0 一.这样做以后能怎样 以device模式编译出app 可以再越狱后的设备上运行 二.要会点什么 命令行,也就是terminal.终端.控制台... vim 三.开始吧 ...

  2. oracle定时执行计划任务

    show parameter job_queue_processes; alter system set job_queue_processes=10; 1,创建测试表 create table jo ...

  3. 面向对象程序设计-C++_课时17函数重载和默认参数

    函数重载,区别一是参数类型不同,二是参数个数不同. 默认参数可以多于1个,但必须放在参数序列的后部. 尽量不要用默认参数,会影响阅读 error C2668: “f”: 对重载函数的调用不明确 #in ...

  4. ubuntu 安装mysql, 以及全然又一次安装的方法

    sudo apt-get install mysql-server 装完后 是无法远程訪问的. 要先改动 sudo vim /etc/mysql/my.cnf 找到 bind-address = 12 ...

  5. a中国天气网pi(json格式)

    http://m.weather.com.cn/data/101050101.html 此接口的回报格式例如以下 { "weatherinfo": { "city&quo ...

  6. asp.net MVC Razor 语法(3)

    编程逻辑:执行基于条件的代码. If 条件 C# 允许您执行基于条件的代码. 如需测试某个条件,您可以使用 if 语句.if 语句会基于您的测试来返回 true 或 false: if 语句启动代码块 ...

  7. opacity在IE6~8下无效果,解决的办法

    opacity在IE6~8下无效果,解决的办法 问题出现时rgba()在ie6下不出效果,最后查到是opacity的问题. opacity是css3时出现的,目前主流浏览器都支持.but老IE是个麻烦 ...

  8. JavaSE思维导图(八)

  9. iOS 根据图片URL从本地相册获取图片

    最近做一个聊天的项目,需要发送图片后读取本地图片显示到列表里.刚开始的时候,天真的认为可以用SDWebImage直接加载,然后并不能行. 于是在网上搜了搜,如何根据从相册获取的UIImagePicke ...

  10. 标准模板库——IO库

    IO库设施: . istream(输入流)类型,提供输入操作. . ostream(输出流)类型,提供输出操作. . cin,一个istream对象,从标准输入读取数据. . cout,一个ostre ...