- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
给定一个未排序的 n
整数集,返回所有大小为 k 的子集(即每个集有 k 个唯一元素)总和为 0。
所以我给了面试官以下解决方案(我在GeekViewpoint上研究过)。没有使用额外的空间,一切都在原地完成,等等。当然,成本是 O(n^k) 的高时间复杂度,其中 k=tuple
在解决方案中。
public void zeroSumTripplets(int[] A, int tuple, int sum) {
int[] index = new int[tuple];
for (int i = 0; i < tuple; i++)
index[i] = i;
int total = combinationSize(A.length, tuple);
for (int i = 0; i < total; i++) {
if (0 != i)
nextCombination(index, A.length, tuple);
printMatch(A, Arrays.copyOf(index, tuple), sum);
}// for
}// zeroSumTripplets(int[], int, int)
private void printMatch(int[] A, int[] ndx, int sum) {
int calc = 0;
for (int i = 0; i < ndx.length; i++)
calc += A[ndx[i]];
if (calc == sum) {
Integer[] t = new Integer[ndx.length];
for (int i = 0; i < ndx.length; i++)
t[i] = A[ndx[i]];
System.out.println(Arrays.toString(t));
}// if
}// printMatch(int[], int[], int)
但随后她提出了以下要求:
她对时间复杂度最感兴趣。
有人知道满足新约束的解决方案吗?
编辑:
据推测,在正确的解决方案中, map 将存储输入的元素,然后 map 将用作查找表,就像 k=2
的情况一样。
当子集的大小为 2(即 k=2
)时,答案很简单:遍历并将所有元素加载到 map 中。然后再次循环输入,这次在 map 中搜索 sum - input[i],其中 i 是从 0 到 n-1 的索引
,这就是答案。假设这个简单的情况可以扩展到 k
是任何东西的地方。
最佳答案
既然没有其他人尝试过,我不妨至少提供一个部分解决方案。正如我在之前的评论中指出的那样,这个问题是 subset sum problem 的变体。在开发此解决方案时,我非常依赖记录在案的解决该问题的方法。
我们正在尝试编写一个函数 subsetsWithSum(A, k, s)
来计算 A 的所有 k 长度子集,这些子集总和为 s。这个问题以两种方式适用于递归解决方案:
递归的基本情况发生在 k 为 1 时,在这种情况下,subsetsWithSum(A, 1, s) 的解是所有单个元素子集的集合,其中该元素等于 s。
所以第一个解决方案是
/**
* Return all k-length subsets of A starting at offset o that sum to s.
* @param A - an unordered list of integers.
* @param k - the length of the subsets to find.
* @param s - the sum of the subsets to find.
* @param o - the offset in A at which to search.
* @return A list of k-length subsets of A that sum to s.
*/
public static List<List<Integer>> subsetsWithSum(
List<Integer> A,
int k,
int s,
int o)
{
List<List<Integer>> results = new LinkedList<List<Integer>>();
if (k == 1)
{
if (A.get(o) == s)
results.add(Arrays.asList(o));
}
else
{
for (List<Integer> sub : subsetsWithSum(A, k-1, s-A.get(o), o+1))
{
List<Integer> newSub = new LinkedList<Integer>(sub);
newSub.add(0, o);
results.add(0, newSub);
}
}
if (o < A.size() - k)
results.addAll(subsetsWithSum(A, k, s, o+1));
return results;
}
现在,请注意,此解决方案通常会使用与之前调用时使用的相同参数集调用 subsetsWithSum(...)。因此,subsetsWithSum 只是乞求成为 memoized .
为了记住函数,我将参数 k、s 和 o 放入一个三元素列表中,这将是从这些参数到之前计算的结果(如果有的话)的映射的关键:
public static List<List<Integer>> subsetsWithSum(
List<Integer> A,
List<Integer> args,
Map<List<Integer>, List<List<Integer>>> cache)
{
if (cache.containsKey(args))
return cache.get(args);
int k = args.get(0), s = args.get(1), o = args.get(2);
List<List<Integer>> results = new LinkedList<List<Integer>>();
if (k == 1)
{
if (A.get(o) == s)
results.add(Arrays.asList(o));
}
else
{
List<Integer> newArgs = Arrays.asList(k-1, s-A.get(o), o+1);
for (List<Integer> sub : subsetsWithSum(A, newArgs, cache))
{
List<Integer> newSub = new LinkedList<Integer>(sub);
newSub.add(0, o);
results.add(0, newSub);
}
}
if (o < A.size() - k)
results.addAll(subsetsWithSum(A, Arrays.asList(k, s, o+1), cache));
cache.put(args, results);
return results;
}
要使用 subsetsWithSum 函数计算所有总和为零的 k 长度子集,可以使用以下函数:
public static List<List<Integer>> subsetsWithZeroSum(List<Integer> A, int k)
{
Map<List<Integer>, List<List<Integer>>> cache =
new HashMap<List<Integer>, List<List<Integer>>> ();
return subsetsWithSum(A, Arrays.asList(k, 0, 0), cache);
}
遗憾的是,我的复杂度计算技巧有点(读作:非常)生疏,所以希望其他人可以帮助我们计算这个解决方案的时间复杂度,但这应该是对蛮力方法的改进。
编辑:为了清楚起见,请注意上面的第一个解决方案在时间复杂度上应该等同于蛮力方法。内存函数在很多情况下应该会有帮助,但在最坏的情况下,缓存永远不会包含有用的结果,时间复杂度将与第一个解决方案相同。另请注意,子集和问题是 NP-complete这意味着任何解决方案都具有指数时间复杂度。 结束编辑。
为了完整性,我测试了这个:
public static void main(String[] args) {
List<Integer> data = Arrays.asList(9, 1, -3, -7, 5, -11);
for (List<Integer> sub : subsetsWithZeroSum(data, 4))
{
for (int i : sub)
{
System.out.print(data.get(i));
System.out.print(" ");
}
System.out.println();
}
}
它打印了:
9 -3 5 -11
9 1 -3 -7
关于java - 给定一组 n 个整数,返回总和为 0 的 k 个元素的所有子集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10423575/
我正在执行大型 ffdf 对象的子集,我注意到当我使用 subset.ff 时,它会生成大量 NA。我通过使用 ffwhich 尝试了另一种方法,结果要快得多,并且没有生成 NA。这是我的测试: li
我对 Prolog 有点陌生。我正在尝试编写一个函数subset(Set, Subset) 来确定Subset 是否是Set 的子集(duh)。另外,如果第二个参数没有实例化,它应该输出每个可能的子集
一、题目 给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。 解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。 二、示例 输入:nums = [1,2
我想从数据帧的操作中排除一列。当然,我可以在没有要排除的列的情况下复制数据框,但这似乎是一种解决方法。我认为必须有一种更简单的方法来进行子集化。 所以这个示例代码应该显示我在做什么。 df colMe
我有一个 SpatialPolygonsDataFrame我通过使用 readOGR 读取 shapefile 创建的在 rgdal包裹。我正在尝试使用它来使用 spsample 生成采样网格在 sp
我想解决一个简单的问题,但即使我尝试了很多不同的方法,我也找不到解决方案。我正在使用 SICStus Prolog (如果这很重要),并且我想获取列表的所有子列表/子集(我不知道哪个术语是正确的),其
我目前正在使用 shinyTable,它是 HandsonTable (https://github.com/trestletech/shinyTable) 的 shiny 兼容实现。巧合的是,我意识
我正在 Delphi 中构建一个表单,其中包含服务下拉列表和用于选择服务的附加组件网格。我获取的数据来自 API,并且我将服务的数据存储在 ADODataSet 中,如下所示: ID (integer
subset() 函数有问题。如何通过观察次数对我的数据框的一个因子进行子集化? NAME CLASS COLOR VALUE antonio
我想知道是否有任何简单的算法来比较一个散列是否是另一个散列的子集。 例如,如果 $HASH{A} = B; $HASH{B} = C; $HASH{C} = D; $HASH2{A} = B; $HA
这个问题在这里已经有了答案: Array combinations without repetition (1 个回答) 关闭 8 年前。 给定一个数组,如何在 postgresql 中找到一定大小
我有下一个程序。我应该如何在 main 中使用迭代器以显示总和为 0 的子集? 我的程序应该打印: 2 -2 5 -5 # include # include using namespace st
我正在寻找一个可以自定义的 Markdown 解析器,最好是 Javascript。特别是,我想删除使用实际 HTML 标签的选项。我尝试编辑摊牌的来源,但无法弄清楚。 Jquery 集成也很好,尽管
我有一个包含名称列表的文件(引用文件 1): Apple Bat Cat 我有另一个文件(引用文件 2),其中包含名称列表和详细信息引用: Apple bla blaa aaaaaaaaagggggg
我有两个带有排序行的文件。一个文件 (B) 是另一个文件 (A) 的子集。我想找到 A 中不在 B 中的所有行。理想情况下,我想创建一个包含这些行的文件 (C)。这在 Unix 中可能吗?我正在寻找一
我有一个包含肽序列的列的数据框,我只想保留字符串中没有内部“R”或“K”的行。 df1 <- data.frame( Peptide = c("ABCOIIJUHFSAUJHR", "AOFI
这个问题在这里已经有了答案: How to subset matrix to one column, maintain matrix data type, maintain row/column na
假设我有一个列表向量: library(tidyverse) d 2) # A tibble: 5 x 1 x 1 2 3 4 5 最佳答案 应该是 lengt
我自己从来没有运行过javadoc(无论是在命令行还是ant's javadoc task;我将使用ant)——我需要为我编写的库生成一个javadoc。 问题是我的 java 库被组织成几个包,在
假设一个多方加密方案,类似于答案:Encryption with multiple different keys? . 那是。一组键K可以用来破译密文。 有没有办法过期: K'⊆ K 这样 K \ K
我是一名优秀的程序员,十分优秀!