【问题标题】:Is there a subarray that sums to a target?是否有一个总和为目标的子数组?
【发布时间】:2020-12-29 07:38:48
【问题描述】:

热门面试问题:

给定一个正整数数组和一个目标整数,求和是否有一个连续的子数组求和。

例如

数组 = [1,3,6,7,8,10] 目标=16 和为 16 的子数组是 [3,6,7],所以它返回 true。

【问题讨论】:

  • 请查看下面给出的答案,谢谢。
  • 等一下...您要使用什么语言?
  • 任何语言都可以。更多的是关于逻辑。 @TimBiegeleisen,您的回答很有意义,而且似乎有效。就复杂性而言,这似乎是 O(N^2)。有什么办法可以提高效率?
  • 我没有意识到您回答了自己的问题 :-) 您可以尝试在 O(NlgN) 时间对数组进行排序,但我看不出排序数组有什么帮助。跨度>
  • 线性时间算法应该可以完成这项工作。

标签: arrays algorithm


【解决方案1】:

刚刚编写并经过全面测试。两种方法,hasConsec(大部分逻辑都在其中)和 sumArr(对数组中的值求和的辅助方法)。 hasConsec 并使用 2 个索引,第一个和最后一个,来创建子数组。 helper 方法用于对创建的子数组求和,然后 hasConsec 检查它是否与目标匹配,是否大于目标,或者是否小于目标。如果匹配,则返回 true;如果总和小于目标,则增加最后一个索引;如果它大于目标,则增加第一个索引。重复直到第一个索引等于数组的长度。如果发生这种情况,则没有与目标相加的子数组。返回假;

public static boolean hasConsec(int arr[], int target) {
    int first = 0, last = 0;

    while (last <  arr.length) {
        int sub[] = Arrays.copyOfRange(arr, first, last);
        int subSum = sumArr(sub);
        if (subSum == target) 
             return true;
        else if (subSum < target)
             last++;
        else {
            if (++first < last)
                last = first;
         }
     }
    return false;
}

public static int sumArr(int arr[]) {
    int sum = 0;
    for (int i = 0; i < arr.length; i++) 
        sum += arr[i];
     return sum;
 }

【讨论】:

    【解决方案2】:

    这个是线性时间(C++ 代码)。

    bool Test(const int* arr, int size, int target) {
      if (target < 0) return false;
      int acc = 0;
      int i = 0, j = 0;
      while (acc != target) {
        if (acc < target) {
          if (j == size) break;
          acc += arr[j++];
        }
        else {
          acc -= arr[i++];
        }
      }
      return acc == target;
    }
    

    请注意,负目标值的预检查对于保证i &lt;= j 的循环不变性是必要的。具体来说,当i == j时,acc将是0,并且一个正目标保证if (acc &lt; target)下的分支被命中。

    【讨论】:

    • @TonyD 我不这么认为。如问题中所述,它假定数组中的正整数。
    • 它似乎错误地处理了 target=0 ......你说“正目标”但检查非负......
    • @gen-y-s 当target0 时,根本不进入while 循环并返回acc == target(即true)。因此,0 的目标值始终会导致返回 true。当我们将空子数组的总和视为0 时,这应该是正确的。
    猜你喜欢
    • 2022-01-12
    • 1970-01-01
    • 2020-06-30
    • 1970-01-01
    • 1970-01-01
    • 2017-01-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多