数组操作:HackerRank问题:JAVA

时间:2019-05-22 05:35:57

标签: java arrays timeoutexception

我正在从hackerrank处执行此数组操作问题,它告诉我编译错误为 由于超时而终止

对于小数组,我的方法可以完美地工作。 此错误仅在较大的数组值时发生。

这是问题链接。 Question Here

  

从1索引的零数组和一个操作列表开始,对于每个操作,在两个给定索引(含两个)之间为每个数组元素添加一个值。完成所有操作后,返回数组中的最大值。

     

例如,零数组的长度。您的查询列表如下:

a b k
1 5 3
4 8 7
6 9 1
     

在索引之间(包括两个端点)添加值:

index -> 1 2 3  4  5 6 7 8 9 10
        [0,0,0, 0, 0,0,0,0,0, 0]
        [3,3,3, 3, 3,0,0,0,0, 0]
        [3,3,3,10,10,7,7,7,0, 0]
        [3,3,3,10,10,8,8,8,1, 0]
     

最大值是在执行所有操作之后。

下面是我的方法。

 static long arrayManipulation(int n, int[][] queries) {
    long max = 0L;
    long[] arr = new long[n];
    for (int i = 0; i < n; i++) {
        arr[i] = 0L;
    }
    for (int i = 0; i < queries.length; i++) {
        int[] q = queries[i];
        int start = q[0] - 1;
        int end = q[1] - 1;
        int val = q[2];
        long tempMax = updateVal(start, end, val, arr);
        if (tempMax > max) {
           max = tempMax;
        }
    }
    return max;
 }



static long updateVal(int start, int end, int val, long[] arr) {
   long max = 0L;
   for (int i = start; i <= end; i++) {
       arr[i] = arr[i] + val;
       if (arr[i] > max) {
           max = arr[i];
       }
   }
   return max;
}

以下给出了一些不适用于我的代码的测试类。
Test1 Test2 Test3

请帮助我解决这个问题。我根据Java搜索了很多答案。
但是我听不懂。
这是我的不得已。请帮忙。

6 个答案:

答案 0 :(得分:2)

首先,如果您不认识它,Terminated due to timeout不是编译错误,则意味着您的实现太慢。面临的挑战是不为该问题实施任何正确的解决方案。解决方案还必须有效。由于您的解决方案效率低下,因此由于输入速度太慢而无法解决大量输入问题。

由于查询的数量似乎比数组的长度小2个数量级(在您发布的3个测试用例中,分别为100K与10M),所以仅处理查询而不是实际使用查询会更有效更新数组。

我不会为您提供一种实现,但我将建议一种比您当前的实现更有效的算法。

我建议您按以下方式处理查询:

  1. 将第一个查询添加到已处理查询的列表中,其中将包含子数组范围不相交的查询。该列表将按第一个数组索引排序(您可以通过在适当位置添加新元素来保持其排序)。

  2. 对于尚未处理的每个查询,查找与查询重叠的所有已处理查询(您可以使用二进制搜索来提高性能)。

    • 以一种方式拆分当前查询,以使结果查询将完全包含在现有处理的查询中,或者不包含在每个现有处理的查询中。

    • 对于在拆分中创建的每个查询:

      • 如果它们的范围等于现有已处理查询的范围,则将查询的值添加到已处理查询。
      • 如果它们的范围不包含在任何现有的已处理查询中,则将该查询添加为新的已处理查询。
      • 如果它们的范围部分包含在现有的已处理查询中,请拆分已处理查询。

我不确定我的解释是否足够清楚。我将用

展示一个例子
1 5 3
4 8 7
6 9 1

输入:

在已处理查询列表中添加1 5 3。

处理4 8 7:有一个处理过的查询与它的重叠部分-1 5 3。

将4 8 7分为两个子查询:4 5 7和6 8 7。

4 5 7包含在1 5 3中,因此将1 5 3分为1 3 3和4 5 3 + 7

6 8 7没有包含在任何已处理的查询中,因此请按原样添加。

现在已处理的查询为:

1 3 3
4 5 10
6 8 7

流程6 9 1:有一个与之重叠的已处理查询:6 8 7。

将6 9 1拆分为两个子查询:6 8 1和9 9 1。

6 8 1具有与6 8 7相同的范围,它将变为6 8 7 + 1

9 9 1没有包含在任何已处理的查询中,因此请按原样添加。

现在已处理的查询为:

1 3 3
4 5 10
6 8 8
9 9 1

在处理查询时,您会跟踪已处理的最大查询值,因此在处理所有查询后,您会知道最大值为10。

答案 1 :(得分:1)

由于给定的时间限制,暴力解决方案在这里不起作用。 这就是您将收到超时错误的原因。

因此,您需要优化代码,这可以借助前缀求和数组来完成。

不是将k加到数组中从a到b的范围内的所有元素上,而是将差值数组累加

每当我们在数组的任何索引处添加任何内容并应用前缀求和算法时,都会将同一元素添加到每个元素,直到数组结尾。

ex- n = 5,m = 1,a = 2 b = 5 k = 5

    i     0.....1.....2.....3.....4.....5.....6   //take array of size N+2 to avoid index out of bound
  A[i]    0     0     0     0     0     0     0

将k = 5添加到a = 2

A [a] = A [a] + k //从应该添加k元素的位置开始索引

     i    0.....1.....2.....3.....4.....5.....6 
   A[i]   0     0     5     0     0     0     0

现在应用前缀和算法

     i    0.....1.....2.....3.....4.....5.....6 
  A[i]    0     0     5     5     5     5     5

因此您可以看到K = 5在应用前缀sum之后添加到所有元素,直到末尾,但是我们不必在末尾添加k。因此,要取消此效果,我们还必须在b + 1索引之后添加-K,以便仅在[a,b]范围内才会有K个元素的添加效果。

A [b + 1] = A [b] -k //删除第b个索引之后先前添加的k元素的影响。 这就是为什么在初始数组中将-k与+ k一起添加。

    i    0.....1.....2.....3.....4.....5.....6 
  A[i]   0     0     5     0     0     0    -5

现在应用前缀和数组

    i    0.....1.....2.....3.....4.....5.....6 
  A[i]   0     0     5     5     5     5     0

您现在可以看到,将K = 5从a = 2添加到b = 5,这是预期的。 在这里,我们只为每个查询更新两个索引,因此复杂度将为O(1)。

现在在输入中应用相同的算法

         # 0.....1.....2.....3.....4.....5.....6    //taken array of size N+2 to avoid index out of bound
5 3      # 0     0     0     0     0     0     0
1 2 100  # 0    100    0   -100    0     0     0       
2 5 100  # 0    100   100  -100    0     0   -100
3 4 100  # 0    100   100    0     0  -100   -100

要计算最大前缀和,请在获取最大累积前缀的同时将差分数组累加到。

执行所有操作后,现在应用前缀求和数组

    i      0.....1.....2.....3.....4.....5.....6 
  A[i]     0     100   200  200   200   100    0

现在您可以遍历此数组以找到最大为200的数组。 遍历数组将花费O(N)时间,而更新每个查询的两个索引将花费O(1)*查询数量(m)

总体复杂度= O(N)+ O(M)                   = O(N + M)

这意味着=(10 ^ 7 + 10 ^ 5)小于10 ^ 8(每秒)

注意:如果要搜索 video tutorial ,则必须将其签出 here 以获得详细说明。< / p>

答案 2 :(得分:1)

针对此问题及其有效的工作,在Java中实施了解决方案。如果需要,请尝试。

  public long arrayManipulation(int n, int[][] queries) 
  {
    if(n==0 || queries==null || queries.length==0){
        return -1;
    }
    long[] computation = new long[n];

    for (int i = 0; i < queries.length; i++) {
    int a = queries[i][0] - 1;
    int b = queries[i][1] - 1;
    int k = queries[i][2];

    computation[a] += k;
    if (b + 1 < n ) {
        computation[b + 1] -= k;
    }
    }

    long max = 0; long sum = 0;
    for (int i = 0; i < n; i++) {
    sum += computation[i];
    max = Math.max(max, sum);
    }

    return max;
}

答案 3 :(得分:1)

static long arrayManipulation(int n, int[][] queries)
{
    // To Avoid "Index was outside the bounds of the array." exception
    long[] numbers = new long[n + 1];

    for(int i = 0; i < queries.length; i++)
    {
        int a = queries[i][0] - 1;
        int b = queries[i][1];
        int k = queries[i][2];

        numbers[a] += k;
        numbers[b] -= k;
    }

    // Calculate sum(s)
    int max=0;
    for(int i = 1; i < numbers.length; i++)
    {
        numbers[i] += numbers[i - 1];
        if(numbers[i]>max)
        {
             max=numbers[i];
        }
    }

    return max;
}

答案 4 :(得分:0)

import java.io.*;
import java.util.InputMismatchException;
import java.util.Random;

public class Solution {
    public static void main(String[] args) {

        InputStream inputStream = System.in;
        InputReader in = new InputReader(inputStream);

        int n = in.readInt();
        int m = in.readInt();

        long[] list = new long[n+3];

        while(m-- > 0) {
            int a = in.readInt();
            int b = in.readInt();
            long k = in.readLong();

            list[a] += k;
            list[b+1] -= k;
        }

        long max = 0;
        long c = 0;
        for (int i = 1; i <= n; i++) {
            c += list[i];
            max = Math.max(max, c);
        }
        System.out.println(max);
    }
}

class InputReader {

    private InputStream stream;
    private byte[] buf = new byte[1024];
    private int curChar;
    private int numChars;
    private SpaceCharFilter filter;

    public InputReader(InputStream stream) {
        this.stream = stream;
    }

    public int read() {
        if (numChars == -1)
            throw new InputMismatchException();
        if (curChar >= numChars) {
            curChar = 0;
            try {
                numChars = stream.read(buf);
            } catch (IOException e) {
                throw new InputMismatchException();
            }
            if (numChars <= 0)
                return -1;
        }
        return buf[curChar++];
    }

    public int peek() {
        if (numChars == -1)
            return -1;
        if (curChar >= numChars) {
            curChar = 0;
            try {
                numChars = stream.read(buf);
            } catch (IOException e) {
                return -1;
            }
            if (numChars <= 0)
                return -1;
        }
        return buf[curChar];
    }

    public int readInt() {
        int c = read();
        while (isSpaceChar(c))
            c = read();
        int sgn = 1;
        if (c == '-') {
            sgn = -1;
            c = read();
        }
        int res = 0;
        do {
            if (c < '0' || c > '9')
                throw new InputMismatchException();
            res *= 10;
            res += c - '0';
            c = read();
        } while (!isSpaceChar(c));
        return res * sgn;
    }

    public long readLong() {
        int c = read();
        while (isSpaceChar(c))
            c = read();
        int sgn = 1;
        if (c == '-') {
            sgn = -1;
            c = read();
        }
        long res = 0;
        do {
            if (c < '0' || c > '9')
                throw new InputMismatchException();
            res *= 10;
            res += c - '0';
            c = read();
        } while (!isSpaceChar(c));
        return res * sgn;
    }

    public boolean isSpaceChar(int c) {
        if (filter != null)
            return filter.isSpaceChar(c);
        return isWhitespace(c);
    }

    public static boolean isWhitespace(int c) {
        return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
    }

    public boolean isExhausted() {
        int value;
        while (isSpaceChar(value = peek()) && value != -1)
            read();
        return value == -1;
    }

    public interface SpaceCharFilter {
        public boolean isSpaceChar(int ch);
    }
}

答案 5 :(得分:-1)

java中用于数组处理hackerank的解决方案... 代码未通过所有情况,因为超时需要改进建议

    static long arrayManipulation(int n, int[][] queries) {
      ArrayList<Long> list = new ArrayList<Long>(n);
      for(int i=0; i<n; i++){
        list.add(i,0l);
      }
      for(int i=0; i<queries.length; i++){
        int s = queries[i][0];
        int e = queries[i][1];
        long k = queries[i][2];
        int size = 0;
        for(int j = s - 1; j<e; j++){

        list.set(j, list.get(j) + k);

        }
      }
      long max  =Collections.max(list);
      return max;

    }