Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/340.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 给定一组n个整数,返回k个元素和为0的所有子集_Java_Time Complexity_Subset Sum - Fatal编程技术网

Java 给定一组n个整数,返回k个元素和为0的所有子集

Java 给定一组n个整数,返回k个元素和为0的所有子集,java,time-complexity,subset-sum,Java,Time Complexity,Subset Sum,给定一组未排序的n整数,返回大小为k的所有子集(即每个集合有k个唯一元素),其总和为0 因此,我给了面试官以下的解决方案(这是我研究的)。没有额外的空间使用,一切都在适当的位置完成,等等。但当然,成本是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

给定一组未排序的
n
整数,返回大小为k的所有子集(即每个集合有k个唯一元素),其总和为0

因此,我给了面试官以下的解决方案(这是我研究的)。没有额外的空间使用,一切都在适当的位置完成,等等。但当然,成本是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)
public void zeroSumTripplets(int[]A,int元组,int和){
int[]索引=新的int[元组];
for(int i=0;i
但随后她提出了以下要求:

  • 答案中必须使用hashmap,以减少时间复杂性
  • 必须绝对地——绝对地——为一般情况提供时间复杂性
  • k=6时的提示,O(n^3)
她对时间复杂性比其他任何东西都感兴趣

有人知道一个可以满足新约束的解决方案吗


编辑:

假设,在正确的解决方案中,映射将存储输入元素,然后映射将用作查找表,就像
k=2
的情况一样

当子集的大小为2(即
k=2
)时,答案很简单:遍历所有元素并将其加载到映射中。然后再次循环输入,这次在映射中搜索
sum-input[i],其中i是从0到n-1的索引,这将是答案。假设这个小例子可以扩展到
k
是任何东西的地方。

@kasavbere-

最近,一位朋友在谷歌上进行了一次艰苦的C++编程工作面试。他的经历和你的相似

这激发了他写这篇文章的灵感——我想你可能会喜欢它:


既然没有其他人尝试过,我不妨至少提出一个部分解决方案。正如我在前面的评论中指出的,这个问题是的一个变体,在开发这个解决方案时,我严重依赖于解决这个问题的文档化方法

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)
我们试图编写一个函数
subsetsum(a,k,s)
,它计算a的所有k长度子集,求和为s。这个问题有两种递归解决方案:

  • 通过计算subsetwithsum(x2…xn,k,s)并添加包括x1的所有有效子集(如果有),可以找到subsetwithsum(x1…xn,k,s)的解;及
  • 可以通过计算SysSt和(AX-XI,K-1,S席)和将席席加入到每个子集(如果有的话)中找到所有包含元素Xi的有效子集。
  • 递归的基本情况发生在k为1时,在这种情况下,subsetsum(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;
    }
    

    我认为您的答案与他们所寻找的非常接近,但是您可以通过注意到大小
    k
    的任何子集都可以被视为大小
    k/2
    的两个子集来提高复杂性。因此,不要查找大小为
    k
    的所有子集(假设
    k
    很小,则取
    O(n^k)
    ),而是使用代码查找大小为
    k/2
    的所有子集,并将每个子集放入哈希表中,其和作为键

    然后用正和迭代大小
    k/2
    的每个子集(称之为sum
    S
    ),并检查哈希表中求和为
    -S
    的子集。如果存在一个,那么大小
    k/2
    的两个子集的组合就是大小
    k
    的一个子集,其总和为零


    因此,在他们给出的
    k=6
    的情况下,您将找到大小为
    3
    的所有子集,并计算它们的总和(这将花费
    O(n^3)
    时间)。然后检查哈希表将花费每个子集的
    O(1)
    时间,因此总时间是
    O(n^3)
    。一般来说,假设
    k
    很小,这种方法将采用
    O(n^(k/2))
    ,您可以通过取大小
    floor(k/2)
    floor(k/2)+1
    的子集,将其推广到
    k
    的奇数值。虽然很有趣,但毫无疑问。你在寻找一个考虑到新增约束的解决方案吗?问:你的问题是?编辑以添加最后一行:
    有人知道一个可以满足新约束的解决方案吗?
    Q:你是说你实际上得到了一个面试问题,你碰巧在GeekViewpoint上学习过这个问题?你能给面试官20多行工作代码?太酷了!因为时间的复杂性,她把你拒之门外?!?这是不是有点像如果你的狗回答法官的问题。。。用法语。。。但是因为你的狗没有正确地修饰她的动词,法官把她记下来了@我承认。我是偶然发现的。事实上,我在网上寻找凯特·厄普顿跳道格舞的视频;)戈尔推荐的;)好文章+1.我喜欢积极的、负责任的反应。虽然我的案子只是一次电话面试,我根本没想到会如此令人生畏,但事实就是这样。如果这里有人有一种快速计算这种不明显的时间复杂度的技术,我将非常感谢他们的投入。向上投票!我测试了你的功能,它们会
    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);
    }
    
    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