Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 

README.rst

Subset sum problem(2Sum, 3Sum, 3SumClosest, 4Sum)

子集和问题:给定一个集合(Set)或者允许重复元素的集合(Multiset),求是否存在一个非空的子集合,使其元素的和为0(或其它给定的值)?这是一个NP完全问题,意味着没有什么高效的解。

指数时间算法

一个幼稚的解法是,使用多层循环,穷尽所有可能的组合,分别求出他们的值,与0比较。对于KSum问题,这个算法的时间复杂度就是O(n^k)。运用hash table或者排序,可以将时间复杂度降为O(n^(k-1))。当固定好前k-2个数后,前k-2个数的和已知,问题变为从剩下的数中找出2个,其和加上前面k-2个数的和为0,即2Sum问题。2Sum问题使用hash table,可以达到O(n)的时间复杂度;如果之前进行了排序,用双指针的方法,也可以得到O(n)的复杂度。于是整个问题的复杂度变为O(n^(k-1))

将N个元素随机地分成2个小集合,每个N/2个元素。对每个小集合,保存一个链表,其中存放所有2^(N/2)种子集合的和。将2个链表都排序,使用标准的排序算法可能会花费O(2^(N/2) * N)的时间,但是给定一个长度为k的有序链表,我们只要另外一个元素,就能得到2个有序链表(其中一个长度为1),接着将2个有序链表合并,会花费O(2^k)。

空间换时间

例如4Sum问题,可以计算任意2个数的和,存入辅助数组。问题转化为,从辅助数组中找出2个数,其和为Sum。需要注意的是,这两个数所取用的元素不能用重合。思路如下:

  1. 创建辅助数组,将任意2个数的和都计算出来,存入其中。辅助数组的大小为n * (n-1) / 2
  2. 将辅助数组排序
  3. 从辅助数组中找出2个数,使得它们的和为sum,且这两个数不是由nums中的同一个数计算出来的

动态规划(伪多项式时间)

设d[i][j]为表示,只能选用nums[0..j-1]的情况下,要找出一个和为i的子序列,是否可能。