求和问题总结(leetcode 2Sum, 3Sum, 4Sum, K Sum)
转自 http://tech-wonderland.net/blog/summary-of-ksum-problems.html
前言:
做过leetcode的人都知道, 里面有2sum, 3sum(closest), 4sum等问题, 这些也是面试里面经典的问题, 考察是否能够合理利用排序这个性质, 一步一步得到高效的算法. 经过总结, 本人觉得这些问题都可以使用一个通用的K sum求和问题加以概括消化, 这里我们先直接给出K Sum的问题描述和算法(递归解法), 然后将这个一般性的方法套用到具体的K, 比如leetcode中的2Sum, 3Sum, 4Sum问题. 同时我们也给出另一种哈希算法的讨论.
leetcode求和问题描述(K sum problem):
K sum的求和问题一般是这样子描述的:给你一组N个数字(比如 vector<int> num), 然后给你一个常数(比如 int target) ,我们的goal是在这一堆数里面找到K个数字,使得这K个数字的和等于target。
注意事项(constraints):
注意这一组数字可能有重复项:比如 1 1 2 3 , 求3sum, 然后 target = 6, 你搜的时候可能会得到 两组1 2 3, 1 2 3,1 来自第一个1或者第二个1, 但是结果其实只有一组,所以最后结果要去重。
K Sum求解方法, 适用leetcode 2Sum, 3Sum, 4Sum:
方法一: 暴力,就是枚举所有的K-subset, 那么这样的复杂度就是 从N选出K个,复杂度是O(N^K)
方法二: 排序,这个算法可以考虑最简单的case, 2sum,这是个经典问题,方法就是先排序,然后利用头尾指针找到两个数使得他们的和等于target, 这个2sum算法网上一搜就有,这里不赘述了,给出2sum的核心代码:
01 |
//2 sum |
02 |
int i = starting; //头指针 |
03 |
int j = num.size() - 1; //尾指针 |
04 |
while (i < j) { |
05 |
int sum = num[i] + num[j]; |
06 |
if (sum == target) { |
07 |
store num[i] and num[j] somewhere; |
08 |
if (we need only one such pair of numbers) |
09 |
break ; |
10 |
otherwise |
11 |
do ++i, --j; |
12 |
} |
13 |
else if (sum < target) |
14 |
++i; |
15 |
else |
16 |
--j; |
17 |
} |
2sum的算法复杂度是O(N log N) 因为排序用了N log N以及头尾指针的搜索是线性的,所以总体是O(N log N),好了现在考虑3sum, 有了2sum其实3sum就不难了,这样想:先取出一个数,那么我只要在剩下的数字里面找到两个数字使得他们的和等于(target – 那个取出的数)就可以了吧。所以3sum就退化成了2sum, 取出一个数字,这样的数字有N个,所以3sum的算法复杂度就是O(N^2 ), 注意这里复杂度是N平方,因为你排序只需要排一次,后面的工作都是取出一个数字,然后找剩下的两个数字,找两个数字是2sum用头尾指针线性扫,这里很容易错误的将复杂度算成O(N^2 log N),这个是不对的。我们继续的话4sum也就可以退化成3sum问题,那么以此类推,K-sum一步一步退化,最后也就是解决一个2sum的问题,K sum的复杂度是O(n^(K-1))。 这个界好像是最好的界了,也就是K-sum问题最好也就能做到O(n^(K-1))复杂度,之前有看到过有人说可以严格数学证明,这里就不深入研究了。
K Sum (2Sum, 3Sum, 4Sum) 算法优化(Optimization):
这里讲两点,第一,注意比如3sum的时候,先整体排一次序,然后枚举第三个数字的时候不需要重复, 比如排好序以后的数字是 a b c d e f, 那么第一次枚举a, 在剩下的b c d e f中进行2 sum, 完了以后第二次枚举b, 只需要在 c d e f中进行2sum好了,而不是在a c d e f中进行2sum, 这个大家可以自己体会一下,想通了还是挺有帮助的。第二,K Sum可以写一个递归程序很优雅的解决,具体大家可以自己试一试。写递归的时候注意不要重复排序就行了。
Hash解法(Other):
其实比如2sum还是有线性解法的,就是用hashmap, 这样你check某个值存在不存在就是常数时间,那么给定一个sum, 只要线性扫描, 对每一个number判断sum – num存在不存在就可以了。注意这个算法对有重复元素的序列也是适用的。比如 2 3 3 4 那么hashtable可以使 hash(2) = 1; hash(3) = 1, hash(4) =1其他都是0, 那么check的时候,扫到两次3都是check sum – 3在不在hashtable中,注意最后返回所有符合的pair的时候也还是要去重。这样子推广的话 3sum 其实也有O(N^2)的类似hash算法,这点和之前是没有提高的,但是4sum就会有更快的一个算法。
4sum的hash算法:
O(N^2)把所有pair存入hash表,并且每个hash值下面可以跟一个list做成map, map[hashvalue] = list,每个list中的元素就是一个pair, 这个pair的和就是这个hash值,那么接下来求4sum就变成了在所有的pair value中求 2sum,这个就成了线性算法了,注意这里的线性又是针对pair数量(N^2)的线性,所以整体上这个算法是O(N^2),而且因为我们挂了list, 所以只要符合4sum的我们都可以找到对应的是哪四个数字。
关于hash的解法我研究还不是很多,以后要是有更深入的研究再更新。
结束语:
这篇文章主要想从一般的K sum问题的角度总结那些比较经典的求和问题比如leetcode里面的2sum, 3sum(closest), 4sum等问题, 文章先直接给出K Sum的问题描述和算法(递归解法), 然后将这个一般性的方法套用到具体的K, 比如leetcode中的2Sum, 3Sum, 4Sum问题. 同时我们也给出另一种哈希算法的讨论. 那么这篇文章基本上还是自己想到什么写什么,有疏忽不对的地方请大家指正,也欢迎留言讨论,如果需要源代码,请留言或者发邮件到info@tech-wonderland.net
(全文完,原创文章,转载时请注明作者和出处)
求和问题总结(leetcode 2Sum, 3Sum, 4Sum, K Sum)的更多相关文章
- LeetCode解题报告--2Sum, 3Sum, 4Sum, K Sum求和问题总结
前言: 这几天在做LeetCode 里面有2sum, 3sum(closest), 4sum等问题, 这类问题是典型的递归思路解题.该这类问题的关键在于,在进行求和求解前,要先排序Arrays.sor ...
- 6.3Sum && 4Sum [ && K sum ] && 3Sum Closest
3Sum Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find a ...
- 2Sum,3Sum,4Sum,kSum,3Sum Closest系列
1).2sum 1.题意:找出数组中和为target的所有数对 2.思路:排序数组,然后用两个指针i.j,一前一后,计算两个指针所指内容的和与target的关系,如果小于target,i右移,如果大于 ...
- 秒杀 2Sum 3Sum 4Sum 算法题
2 Sum 这题是 Leetcode 的第一题,相信大部分小伙伴都听过的吧. 作为一道标着 Easy 难度的题,它真的这么简单吗? 我在之前的刷题视频里说过,大家刷题一定要吃透一类题,为什么有的人题目 ...
- k sum 问题系列
转自:http://tech-wonderland.net/blog/summary-of-ksum-problems.html (中文旧版)前言: 做过leetcode的人都知道, 里面有2sum, ...
- LeetCode Two Sum&Two Sum II - Input array is sorted&3Sum&4Sum 一锅煮题解
文章目录 Two Sum Two Sum II 3Sum 4Sum Two Sum 题意 给定一个数组,和指定一个目标和.从数组中选择两个数满足和为目标和.保证有且只有一个解.每个元素只可以用一次. ...
- 【LeetCode】18. 4Sum 四数之和
作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 个人公众号:负雪明烛 本文关键词:four sum, 4sum, 四数之和,题解,leet ...
- [LeetCode][Python]18: 4Sum
# -*- coding: utf8 -*-'''__author__ = 'dabay.wang@gmail.com' 18: 4Sumhttps://oj.leetcode.com/problem ...
- 【LeetCode】3Sum 解决报告
这个问题是我目前的知识回答,不来,只有良好的网上搜索解决方案,发现 K Sum 它是一类问题,但是,互联网是没有更简洁的代码,我想对于谁刚开始学习的人.您可能仍然想看看这个问题该怎么解决,然后看看他们 ...
随机推荐
- Ajax 技术一
一.Ajax概述 1.历史起源 1998年,微软公司Outlook Web Access研发小组在当时的IE浏览器中集成了一种技术,可以在客户端无刷新的前提下向服务器端发送Http请求,这门技术称之为 ...
- CPU卡及NFC供应商
1.苏州市民卡供应商 北京握奇数据/watchdata 2.苏州市民卡手表 苏州连爱/linklove公司 3.NFC供应商 英飞凌/Infelion, NXP,复旦微电子, 4.什么是CPU卡? C ...
- unity基本操作二
一:error1,先断网再启动点击Manual Activation点击Save License生成相应的alf文件2,联网打开https://license.unity3d.com/manual上传 ...
- 9.配置postfix空客户端
将本地邮件服务器配置充当为控客户端,已将所有邮件都转发到中央服务器以进行发送 1.postconf -e "relayhost=[mail.example.com]" 邮件被路由到 ...
- PHP性能优化-编译级别的缓存
最近安装了 php5.6,发现有了 opcache.so扩展文件,于是,搜索了一下,发现 zend opcache已经融入到 ph5.5以上的版本了,即兴奋,不用再去找xcache,apc,eAcce ...
- 批处理cmd背景颜色
Pause Echo 其他提示语 & pause > nul pause暂停 COLOR 设置默认的控制台前景和背景颜色. COLOR [attr] attr 指定控制台输出的 ...
- php多层数组与对象的转换实例代码
通过json_decode(json_encode($object)可以将对象一次性转换为数组,但是object中遇到非utf-8编码的非ascii字符则会出现问题,比如gbk的中文,何况json_e ...
- JQuery解析JSon
JsonCreatet.ashx页面 JSonAnalysis.aspx测试页面 一般处理程序中使用Newtonsoft.Json来序列化json 页面使用Jquery 来解析Json数据 Jquer ...
- Python操作列表的常用方法
下面列出列表常用的方法操作列表以及小例子: 1. Append 在列表末尾添加元素,需在列表末尾添加元素,需要注意几个点: A. append中添加的参数是作为一个整体 & ...
- 1066. Root of AVL Tree (25)
An AVL tree is a self-balancing binary search tree. In an AVL tree, the heights of the two child sub ...