我正在从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搜索了很多答案。
但是我听不懂。
这是我的不得已。请帮忙。
答案 0 :(得分:2)
首先,如果您不认识它,Terminated due to timeout
不是编译错误,则意味着您的实现太慢。面临的挑战是不为该问题实施任何正确的解决方案。解决方案还必须有效。由于您的解决方案效率低下,因此由于输入速度太慢而无法解决大量输入问题。
由于查询的数量似乎比数组的长度小2个数量级(在您发布的3个测试用例中,分别为100K与10M),所以仅处理查询而不是实际使用查询会更有效更新数组。
我不会为您提供一种实现,但我将建议一种比您当前的实现更有效的算法。
我建议您按以下方式处理查询:
将第一个查询添加到已处理查询的列表中,其中将包含子数组范围不相交的查询。该列表将按第一个数组索引排序(您可以通过在适当位置添加新元素来保持其排序)。
对于尚未处理的每个查询,查找与查询重叠的所有已处理查询(您可以使用二进制搜索来提高性能)。
以一种方式拆分当前查询,以使结果查询将完全包含在现有处理的查询中,或者不包含在每个现有处理的查询中。
对于在拆分中创建的每个查询:
我不确定我的解释是否足够清楚。我将用
展示一个例子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;
}