在编纂测试中NumberOfDiscIntersections我得到了100%的正确率和87%的正确率,其中一次测试失败了
overflow
arithmetic overflow tests
got -1 expected 2
我无法看到导致我使用的是64位长的原因。即使我能100%达到100%正确性,我想知道是否有更好的方法来做到这一点,而不是Java中的冗长。
编辑:找出一个更好的方法来处理两个数组而不是一对类
// you can also use imports, for example:
import java.util.*;
// you can use System.out.println for debugging purposes, e.g.
// System.out.println("this is a debug message");
class Solution {
public int solution(int[] A) {
int j = 0;
Pair[] arr = new Pair[A.length * 2];
for (int i = 0; i < A.length; i++) {
Pair s = new Pair(i - A[i], true);
arr[j] = s;
j++;
Pair e = new Pair(i + A[i], false);
arr[j] = e;
j++;
}
Arrays.sort(arr, new Pair(0, true));
long numIntersect = 0;
long currentCount = 0;
for (Pair p: arr) {
if (p.start) {
numIntersect += currentCount;
if (numIntersect > 10000000) {
return -1;
}
currentCount++;
} else {
currentCount--;
}
}
return (int) numIntersect;
}
static private class Pair implements Comparator<Pair> {
private long x;
private boolean start;
public Pair(long x, boolean start) {
this.x = x;
this.start = start;
}
public int compare(Pair p1, Pair p2) {
if (p1.x < p2.x) {
return -1;
} else if (p1.x > p2.x) {
return 1;
} else {
if (p1.start && p2.start == false) {
return -1;
} else if (p1.start == false && p2.start) {
return 1;
} else {
return 0;
}
}
}
}
}
答案 0 :(得分:1)
看看这一行:
Pair s = new Pair(i + A[i], true);
这相当于Pair s = new Pair((long)(i + A[i]) , true);
由于i
是整数,A[i]
也是整数,因此这可能会导致溢出,因为A[i]
中的值最多可以达到Integer.MAX_VALUE
,并且转换为添加操作完成后发生了long
。
修复:
Pair s = new Pair((long)i + (long)A[i], true);
注意:我已经提交了我的固定版并获得了100%
答案 1 :(得分:1)
我今天的解决方案。 O(N)时间复杂度。简单假设表的下一个点中的可用对数是该时刻的总开放圆(圆)与之前已处理过的圆之间的差。也许很简单:)
public int solution04(int[] A) {
final int N = A.length;
final int M = N + 2;
int[] left = new int[M]; // values of nb of "left" edges of the circles in that point
int[] sleft = new int[M]; // prefix sum of left[]
int il, ir; // index of the "left" and of the "right" edge of the circle
for (int i = 0; i < N; i++) { // counting left edges
il = tl(i, A);
left[il]++;
}
sleft[0] = left[0];
for (int i = 1; i < M; i++) {// counting prefix sums for future use
sleft[i]=sleft[i-1]+left[i];
}
int o, pairs, total_p = 0, total_used=0;
for (int i = 0; i < N; i++) { // counting pairs
ir = tr(i, A, M);
o = sleft[ir]; // nb of open till right edge
pairs = o -1 - total_used;
total_used++;
total_p += pairs;
}
if(total_p > 10000000){
total_p = -1;
}
return total_p;
}
int tl(int i, int[] A){
int tl = i - A[i]; // index of "begin" of the circle
if (tl < 0) {
tl = 0;
} else {
tl = i - A[i] + 1;
}
return tl;
}
int tr(int i, int[] A, int M){
int tr; // index of "end" of the circle
if (Integer.MAX_VALUE - i < A[i] || i + A[i] >= M - 1) {
tr = M - 1;
} else {
tr = i + A[i] + 1;
}
return tr;
}
答案 2 :(得分:0)
我对此表示赞同,O(n):
public int solution(int[] A) {
int[] startPoints = new int[A.length];
int[] endPoints = new int[A.length];
int tempPoint;
int currOpenCircles = 0;
long pairs = 0;
//sum of starting and end points - how many circles open and close at each index?
for(int i = 0; i < A.length; i++){
tempPoint = i - A[i];
startPoints[tempPoint < 0 ? 0 : tempPoint]++;
tempPoint = i + A[i];
if(A[i] < A.length && tempPoint < A.length) //first prevents int overflow, second chooses correct point
endPoints[tempPoint]++;
}
//find all pairs of new circles (combinations), then make pairs with exiting circles (multiplication)
for(int i = 0; i < A.length; i++){
if(startPoints[i] >= 2)
pairs += (startPoints[i] * (startPoints[i] - 1)) / 2;
pairs += currOpenCircles * startPoints[i];
currOpenCircles += startPoints[i];
currOpenCircles -= endPoints[i];
if(pairs > 10000000)
return -1;
}
return (int) pairs;
}
答案 3 :(得分:0)
Helsing解决方案部分的解释:
if(startPoints[i] >= 2) pairs += (startPoints[i] * (startPoints[i] - 1)) / 2;
基于数学组合公式:
Cn,m = n! / ((n-m)!.m!
对于配对,则m = 2,然后:
Cn,2 = n! / ((n-2)!.2
等于:
Cn,2 = n.(n-1).(n-2)! / ((n-2)!.2
通过简化:
Cn,2 = n.(n-1) / 2
答案 4 :(得分:0)
性能不是很好,但是使用流。
List<Long> list = IntStream.range(0, A.length).mapToObj(i -> Arrays.asList((long) i - A[i], (long) i + A[i]))
.sorted((o1, o2) -> {
int f = o1.get(0).compareTo(o2.get(0));
return f == 0 ? o1.get(1).compareTo(o2.get(1)) : f;
})
.collect(ArrayList<Long>::new,
(acc, val) -> {
if (acc.isEmpty()) {
acc.add(0l);
acc.add(val.get(1));
} else {
Iterator it = acc.iterator();
it.next();
while (it.hasNext()) {
long el = (long) it.next();
if (val.get(0) <= el) {
long count = acc.get(0);
acc.set(0, ++count);
} else {
it.remove();
}
}
acc.add(val.get(1));
}
},
ArrayList::addAll);
return (int) (list.isEmpty() ? 0 : list.get(0) > 10000000 ? -1 : list.get(0));