当前位置: 首页 > 知识库问答 >
问题:

正在使用ArrayList。for循环中的contains()实际上比使用嵌套循环进行比较更有效?

慕乐池
2023-03-14

我一直在做一些实践技术面试问题,这个问题很容易,但是我想知道我的两个解决方案中更有效的是否真的如此。

我现在看到这里的其他人以前问过这个问题,但我的问题有代码片段,我觉得它可能会为其他正在寻找解决方案的人提供进一步的见解。

问题是:给定一个整数数组和一些数字k,创建一个函数,如果数组中的任意两个数字与k相加,则返回true。

以下是我的“慢”解决方案:

private static boolean canAddToKSlow(int[] nums, int k) {
    /*
    Uses double for loops to compare each value in the array to
    another value (not including the current one). If they add
    up to k, return true. Otherwise, at the end of iteration,
    return false.
    */

    for(int i = 0; i < nums.length; i++) {
      for(int j = 0; j < nums.length; j++) {
        if (j != i) {
          if (nums[i] + nums[j] == k) {
            return true;
          }
        }
      }
    }

    return false;
  }

还有我的“快速”解决方案:

private static boolean canAddToKFast(int[] nums, int k) {
    /*
    Uses a single optimized for loop to iterate through the list,
    and adds the "complement" of the current int to the arraylist.
    By complement, I mean whatever number you would have to add to
    n to get k. Then, it checks to see if that n is in the arraylist, and if so, then there must be two numbers that 
    add to k. More efficient.
    */
    ArrayList<Integer> comps = new ArrayList<>();

    for(int n: nums) {
      comps.add(k - n);
      if(comps.contains(n))
        return true;

    }

    return false;
 }

我遇到的问题是ArrayList。contains()调用indexOf(),indexOf()无论如何都会用于循环,因此它可能同样低效,而且只是混淆了。有没有巫毒魔法能让第二种解决方案更有效?如果没有,实际上有没有一种方法可以提高效率,或者这是你能做到的最好的方法?我想知道散列表是否会有什么不同。

共有2个答案

金谭三
2023-03-14

下面是一个使用哈希表的O(n)解决方案,但它确实使用了额外的空间:

    private static boolean canAddToKFast2(int[] nums, int k) {

        Map<Integer,Integer> table = new HashMap<Integer, Integer>();

        for(int val: nums) {
            if(table.containsKey(k - val)) { // O(1) lookup to see if the difference exists
                return true;
            }
            table.put(val, val); //If it doesn't exist, add the value to the table
        }
        return false; // We searched all values and didn't find a pair
    }

这是O(n)时间,我们可以看到,因为我们只接触每个元素一次。如果目标减去元素不存在于表中,那么我们将其插入到表中。如果我们遍历所有项,但没有找到匹配项,则返回false。

那空间效率呢?

关于你的面试,我想问是否允许额外的空间(哈希表将使用O(n²)空间)。如果不允许额外的空间,那么最有效的答案是你问题中的代码(在O(n²)时间内运行,不使用任何额外的空间。

狄冠宇
2023-03-14

在这两种情况下,效率没有差别,因为list。contains()的时间复杂度为O(n),因此两者的时间复杂度均为O(n²)。

更好的解决方案是使用HashSet。contains()的时间复杂度为O(1)。

这个类为基本操作(添加、删除、包含和大小)提供了恒定的时间性能,前提是哈希函数将元素正确地分散在存储桶中。(文件)

所以这个的时间复杂度是O(n):

private static boolean canAddToKFast2(int[] nums, int k) {
    Set<Integer> comps = new HashSet<>();
    for (int n : nums) {
        if (comps.contains(n))
            return true;
        comps.add(k - n);
    }
    return false;
}

 类似资料:
  • 我在下面的代码中使用了嵌套的for循环,并且我有一些条件来中断内部的for循环,这提高了代码的性能。 现在,如何使用 Java 8 流来执行相同的逻辑?我想出了下面的代码: 在这里,我不能在java流中使用< code>break语句,所以我使用了< code>return语句,但它仍然运行内部循环,因为它不会中断内部循环,所以性能没有提高。

  • 对Java来说很新鲜,我在大学的一个入门班做一个项目。我正在尝试做一个方法,在String数组中搜索输入的状态并返回索引。如果用户输入不在数组中的查询,我希望它要求一个新的状态来搜索。我的例外是说“变量statePotion可能尚未初始化。”下面是代码。 提前谢谢!

  • 问题内容: 我读到 增强的for循环 比普通的 for循环 更有效: http://developer.android.com/guide/practices/performance.html#foreach 当我搜索它们的效率之间的差异时,我发现的是:如果是普通的for循环,我们需要一个额外的步骤来找出数组的长度或大小等, 但这是唯一的原因,增强的for循环优于普通的for循环吗?在那种情况下,

  • 我有一个嵌套的for循环,但是它会减慢一点处理速度,我如何才能使嵌套循环高效。我需要的是对于外循环的每个值,内循环继续其所有迭代。但是,我不认为它会像两个嵌套循环那样影响计算。我的第二个问题是,循环会影响速度还是会支持我的现象? 我的代码:

  • 和其他编程语言一样, Java 允许循环嵌套。如果把一个循环放在另一个循环体内,那么就可以形成嵌套循环。 嵌套循环既可以是 for循环嵌套 while 循环,也可以是 while 循环嵌套 do-while 循环 …… 即各种类型的循环都可以作为外层循环,也可以作为内层循环。 当程序遇到嵌套循环时,如果外层循环的循环条件允许,则开始执行外层循环的循环体,而内层循环将被外层循环的循环体来执行——只是

  • 我使用以下程序集和c源(分别使用fasm和gcc)将一些程序集与一些c链接起来,以测试函数调用的成本 组件: c来源: 我得到的结果令人惊讶。首先,速度取决于我链接的顺序。如果我以的形式链接,典型的输出是 但是以相反的顺序链接,我得到了一个更像的输出: 他们的不同令人惊讶,但这不是我要问的问题。(此处有相关问题) 我要问的问题是,在第二次运行中,有函数调用的循环如何比没有函数调用的循环快,调用函数