给定A
个N
整数数组,我们在2D平面中绘制N
个光盘,这样第i个光盘的中心位于(0,i)
和半径{{ 1}}。如果第k个和第j个盘具有至少一个公共点,我们说第k个盘和第j个盘相交。
写一个函数
A[i]
如上所述,给出描述int number_of_disc_intersections(int[] A);
光盘的数组A
的返回相交光盘对的数量。例如,给定N
和
N=6
有11对交叉光盘:
A[0] = 1
A[1] = 5
A[2] = 2
A[3] = 1
A[4] = 4
A[5] = 0
所以函数应该返回11。
如果交叉对的数量超过10,000,000,则该函数应返回-1。该函数可以假设0th and 1st
0th and 2nd
0th and 4th
1st and 2nd
1st and 3rd
1st and 4th
1st and 5th
2nd and 3rd
2nd and 4th
3rd and 4th
4th and 5th
不超过10,000,000。
答案 0 :(得分:67)
O(N)复杂度和O(N)内存解决方案。
private static int Intersections(int[] a)
{
int result = 0;
int[] dps = new int[a.length];
int[] dpe = new int[a.length];
for (int i = 0, t = a.length - 1; i < a.length; i++)
{
int s = i > a[i]? i - a[i]: 0;
int e = t - i > a[i]? i + a[i]: t;
dps[s]++;
dpe[e]++;
}
int t = 0;
for (int i = 0; i < a.length; i++)
{
if (dps[i] > 0)
{
result += t * dps[i];
result += dps[i] * (dps[i] - 1) / 2;
if (10000000 < result) return -1;
t += dps[i];
}
t -= dpe[i];
}
return result;
}
答案 1 :(得分:60)
因此,您希望找到间隔[i-A[i], i+A[i]]
的交叉点数。
维护一个包含i-A[i]
的排序数组(称之为X)(还有一些额外的空格,其中包含值i+A[i]
)。
现在从最左边的间隔(即最小i-A[i]
)开始走数组X.
对于当前间隔,进行二分搜索以查看间隔的右端点(即i+A[i]
)将去向何处(称为等级)。现在您知道它与左侧的所有元素相交。
增加一个具有等级的计数器并减去当前位置(假设一个被索引),因为我们不想重复计算间隔和自交叉。
O(nlogn)时间, O(n)空间。
答案 2 :(得分:12)
好吧,我将FalkHüffner的想法改编为c ++,并改变了范围。 与上面所写的相反,没有必要超出数组的范围(无论数值有多大)。 在Codility上,这段代码收到了100%。 谢谢Falk你的好主意!
int number_of_disc_intersections ( const vector<int> &A ) {
int sum=0;
vector<int> start(A.size(),0);
vector<int> end(A.size(),0);
for (unsigned int i=0;i<A.size();i++){
if ((int)i<A[i]) start[0]++;
else start[i-A[i]]++;
if (i+A[i]>=A.size()) end[A.size()-1]++;
else end[i+A[i]]++;
}
int active=0;
for (unsigned int i=0;i<A.size();i++){
sum+=active*start[i]+(start[i]*(start[i]-1))/2;
if (sum>10000000) return -1;
active+=start[i]-end[i];
}
return sum;
}
答案 3 :(得分:10)
这甚至可以在线性时间内完成。实际上,如果忽略每个点上只有一个区间,并将其视为一组间隔的起点和终点这一事实,就会变得更容易。然后,您可以从左侧扫描它(Python代码为了简单起见):
from collections import defaultdict
a = [1, 5, 2, 1, 4, 0]
start = defaultdict(int)
stop = defaultdict(int)
for i in range(len(a)):
start[i - a[i]] += 1
stop[i + a[i]] += 1
active = 0
intersections = 0
for i in range(-len(a), len(a)):
intersections += active * start[i] + (start[i] * (start[i] - 1)) / 2
active += start[i]
active -= stop[i]
print intersections
答案 4 :(得分:10)
这是一个 O(N)时间, O(N)空间算法需要在整个数组中运行3次并且没有排序,verified scoring 100%:
你对成对的光盘感兴趣。每对涉及一个盘的一侧和另一盘的另一侧。因此,如果我们处理每张光盘的一面,我们就不会有重复对。让我们左右两边调用(我在思考它的同时旋转了空间)。
重叠是由于右侧直接在中心处重叠另一个光盘(因此对半径等于半径而非常关心阵列长度),或者是由于最左边存在左侧的数量。
所以我们创建一个数组,其中包含每个点的左边数,然后它就是一个简单的总和。
C代码:
int solution(int A[], int N) {
int C[N];
int a, S=0, t=0;
// Mark left and middle of disks
for (int i=0; i<N; i++) {
C[i] = -1;
a = A[i];
if (a>=i) {
C[0]++;
} else {
C[i-a]++;
}
}
// Sum of left side of disks at location
for (int i=0; i<N; i++) {
t += C[i];
C[i] = t;
}
// Count pairs, right side only:
// 1. overlaps based on disk size
// 2. overlaps based on disks but not centers
for (int i=0; i<N; i++) {
a = A[i];
S += ((a<N-i) ? a: N-i-1);
if (i != N-1) {
S += C[((a<N-i) ? i+a: N-1)];
}
if (S>10000000) return -1;
}
return S;
}
答案 5 :(得分:8)
Python 100/100(已测试)关于编码,具有O(nlogn)时间和O(n)空间。
这是@noisyboiler的@Aryabhatta方法的python实现,带有注释和示例。 完全归功于原作者,任何错误/不良措辞完全是我的错。
from bisect import bisect_right
def number_of_disc_intersections(A):
pairs = 0
# create an array of tuples, each containing the start and end indices of a disk
# some indices may be less than 0 or greater than len(A), this is fine!
# sort the array by the first entry of each tuple: the disk start indices
intervals = sorted( [(i-A[i], i+A[i]) for i in range(len(A))] )
# create an array of starting indices using tuples in intervals
starts = [i[0] for i in intervals]
# for each disk in order of the *starting* position of the disk, not the centre
for i in range(len(starts)):
# find the end position of that disk from the array of tuples
disk_end = intervals[i][1]
# find the index of the rightmost value less than or equal to the interval-end
# this finds the number of disks that have started before disk i ends
count = bisect_right(starts, disk_end )
# subtract current position to exclude previous matches
# this bit seemed 'magic' to me, so I think of it like this...
# for disk i, i disks that start to the left have already been dealt with
# subtract i from count to prevent double counting
# subtract one more to prevent counting the disk itsself
count -= (i+1)
pairs += count
if pairs > 10000000:
return -1
return pairs
工作示例:给定[3,0,1,6],磁盘半径如下所示:
disk0 ------- start= -3, end= 3
disk1 . start= 1, end= 1
disk2 --- start= 1, end= 3
disk3 ------------- start= -3, end= 9
index 3210123456789 (digits left of zero are -ve)
intervals = [(-3, 3), (-3, 9), (1, 1), (1,3)]
starts = [-3, -3, 1, 1]
the loop order will be: disk0, disk3, disk1, disk2
0th loop:
by the end of disk0, 4 disks have started
one of which is disk0 itself
none of which could have already been counted
so add 3
1st loop:
by the end of disk3, 4 disks have started
one of which is disk3 itself
one of which has already started to the left so is either counted OR would not overlap
so add 2
2nd loop:
by the end of disk1, 4 disks have started
one of which is disk1 itself
two of which have already started to the left so are either counted OR would not overlap
so add 1
3rd loop:
by the end of disk2, 4 disks have started
one of which is disk2 itself
two of which have already started to the left so are either counted OR would not overlap
so add 0
pairs = 6
to check: these are (0,1), (0,2), (0,2), (1,2), (1,3), (2,3),
答案 6 :(得分:5)
我用这个C ++实现得到100分中的100分:
#include <map>
#include <algorithm>
inline bool mySortFunction(pair<int,int> p1, pair<int,int> p2)
{
return ( p1.first < p2.first );
}
int number_of_disc_intersections ( const vector<int> &A ) {
int i, size = A.size();
if ( size <= 1 ) return 0;
// Compute lower boundary of all discs and sort them in ascending order
vector< pair<int,int> > lowBounds(size);
for(i=0; i<size; i++) lowBounds[i] = pair<int,int>(i-A[i],i+A[i]);
sort(lowBounds.begin(), lowBounds.end(), mySortFunction);
// Browse discs
int nbIntersect = 0;
for(i=0; i<size; i++)
{
int curBound = lowBounds[i].second;
for(int j=i+1; j<size && lowBounds[j].first<=curBound; j++)
{
nbIntersect++;
// Maximal number of intersections
if ( nbIntersect > 10000000 ) return -1;
}
}
return nbIntersect;
}
答案 7 :(得分:2)
这是我的JavaScript解决方案,基于该线程中的其他解决方案,但以其他语言实现。
function solution(A) {
let circleEndpoints = [];
for(const [index, num] of Object.entries(A)) {
circleEndpoints.push([parseInt(index)-num, true]);
circleEndpoints.push([parseInt(index)+num, false]);
}
circleEndpoints = circleEndpoints.sort(([a, openA], [b, openB]) => {
if(a == b) return openA ? -1 : 1;
return a - b;
});
let openCircles = 0;
let intersections = 0;
for(const [endpoint, opening] of circleEndpoints) {
if(opening) {
intersections += openCircles;
openCircles ++;
} else {
openCircles --;
}
if(intersections > 10000000) return -1;
}
return intersections;
}
答案 8 :(得分:2)
Python回答
from bisect import bisect_right
def number_of_disc_intersections(li):
pairs = 0
# treat as a series of intervals on the y axis at x=0
intervals = sorted( [(i-li[i], i+li[i]) for i in range(len(li))] )
# do this by creating a list of start points of each interval
starts = [i[0] for i in intervals]
for i in range(len(starts)):
# find the index of the rightmost value less than or equal to the interval-end
count = bisect_right(starts, intervals[i][1])
# subtract current position to exclude previous matches, and subtract self
count -= (i+1)
pairs += count
if pairs > 10000000:
return -1
return pairs
答案 9 :(得分:2)
Java 2 * 100%。
result
被宣布为一个案例,但是一个案件的密集性没有进行测试,即在一个点上有50k * 50k的交叉点。
class Solution {
public int solution(int[] A) {
int[] westEnding = new int[A.length];
int[] eastEnding = new int[A.length];
for (int i=0; i<A.length; i++) {
if (i-A[i]>=0) eastEnding[i-A[i]]++; else eastEnding[0]++;
if ((long)i+A[i]<A.length) westEnding[i+A[i]]++; else westEnding[A.length-1]++;
}
long result = 0; //long to contain the case of 50k*50k. codility doesn't test for this.
int wests = 0;
int easts = 0;
for (int i=0; i<A.length; i++) {
int balance = easts*wests; //these are calculated elsewhere
wests++;
easts+=eastEnding[i];
result += (long) easts*wests - balance - 1; // 1 stands for the self-intersection
if (result>10000000) return -1;
easts--;
wests-= westEnding[i];
}
return (int) result;
}
}
答案 10 :(得分:1)
我提供另一种解决方案,因为我没有发现之前解决方案的计数原理易于遵循。虽然结果相同,但似乎值得展示一个解释和更直观的计数过程。
首先,首先考虑 O(N^2) 解决方案,该解决方案按照圆盘的中心点的顺序迭代圆盘,并计算与当前圆盘相交的以当前圆盘右侧为中心的圆盘数量,使用条件 current_center + radius >= other_center - radius。请注意,我们可以使用条件 current_center - radius <= other_center + radius 获得相同的结果,计算以当前圆盘左侧为中心的圆盘。
def simple(A):
"""O(N^2) solution for validating more efficient solution."""
N = len(A)
unique_intersections = 0
# Iterate over discs in order of their center positions
for j in range(N):
# Iterate over discs whose center is to the right, to avoid double-counting.
for k in range(j+1, N):
# Increment cases where edge of current disk is at or right of the left edge of another disk.
if j + A[j] >= k - A[k]:
unique_intersections += 1
# Stop early if we have enough intersections.
# BUT: if the discs are small we still N^2 compare them all and time out.
if unique_intersections > 10000000:
return -1
return unique_intersections
如果我们只能“查找”与当前圆盘相交的右侧(或左侧!)圆盘的数量,我们可以从 O(N^2) 到 O(N)。关键的见解是将相交条件重新解释为“一个圆盘的右边缘与另一个圆盘的左边缘重叠”,这意味着(哈哈!)中心无关紧要,只有边缘。
下一个见解是尝试对边进行排序,花费 O(N log N) 时间。给定左边缘的排序数组和右边缘的排序数组,当我们沿着数轴从左到右扫描时,当前位置点左侧的左边缘或右边缘的数量就是当前分别索引到 left_edges 和 right_edges:恒定时间推导。
最后,我们使用“右边缘>左边缘”条件来推导出当前磁盘与仅从当前磁盘左侧开始的磁盘之间的交叉点数(以避免重复) 是当前边左侧的左侧边数减去当前边左侧的右侧边数。也就是说,从这个开始左边的盘数减去已经关闭的盘数。
现在对于这段代码,在 Codility 上进行了 100% 的测试:
def solution(A):
"""O(N log N) due to sorting, with O(N) pass over sorted arrays"""
N = len(A)
# Left edges of the discs, in increasing order of position.
left_edges = sorted([(p-r) for (p,r) in enumerate(A)])
# Right edges of the discs, in increasing order of position.
right_edges = sorted([(p+r) for (p,r) in enumerate(A)])
#print("left edges:", left_edges[:10])
#print("right edges:", right_edges[:10])
intersections = 0
right_i = 0
# Iterate over the discs in order of their leftmost edge position.
for left_i in range(N):
# Find the first right_edge that's right of or equal to the current left_edge, naively:
# right_i = bisect.bisect_left(right_edges, left_edges[left_i])
# Just scan from previous index until right edge is at or beyond current left:
while right_edges[right_i] < left_edges[left_i]:
right_i += 1
# Count number of discs starting left of current, minus the ones that already closed.
intersections += left_i - right_i
# Return early if we find more than 10 million intersections.
if intersections > 10000000:
return -1
#print("correct:", simple(A))
return intersections
答案 11 :(得分:1)
count = 0
for (int i = 0; i < N; i++) {
for (int j = i+1; j < N; j++) {
if (i + A[i] >= j - A[j]) count++;
}
}
O(N^2)
这么慢,但它确实有效。
答案 12 :(得分:1)
我知道这是一个古老的问题,但它在编码方面仍然很活跃。
private int solution(int[] A)
{
int openedCircles = 0;
int intersectCount = 0;
我们需要带有其开始和结束值的圆。为此,我使用了Tuple。 正确/错误表示我们要添加“圆环起点”还是“圆环终点”值。
List<Tuple<decimal, bool>> circles = new List<Tuple<decimal, bool>>();
for(int i = 0; i < A.Length; i ++)
{
// Circle start value
circles.Add(new Tuple<decimal, bool>((decimal)i - (decimal)A[i], true));
// Circle end value
circles.Add(new Tuple<decimal, bool>((decimal)i + (decimal)A[i], false));
}
按其值对“圆圈”进行排序。 如果一个圆在另一个圆的起点处以相同的值结束,则应将其视为相交(因为如果在同一点,则“开口”应位于“闭合”的前面)
circles = circles.OrderBy(x => x.Item1).ThenByDescending(x => x.Item2).ToList();
计数和返回计数器
foreach (var circle in circles)
{
// We are opening new circle (within existing circles)
if(circle.Item2 == true)
{
intersectCount += openedCircles;
if (intersectCount > 10000000)
{
return -1;
}
openedCircles++;
}
else
{
// We are closing circle
openedCircles--;
}
}
return intersectCount;
}
答案 13 :(得分:1)
可能非常快。上)。但是您需要检查一下。 100%的Codility。 大意: 1.在表格的任何一点,直到圆圈的右边缘都有“打开”的圆圈数,让我们说“ o”。 2.因此,该点的圆存在(对o-1个)可能的对。 “已用”是指已处理的圆并已计算成对。
public int solution(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;
}
private 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;
}
答案 14 :(得分:1)
100/100 c#
class Solution
{
class Interval
{
public long Left;
public long Right;
}
public int solution(int[] A)
{
if (A == null || A.Length < 1)
{
return 0;
}
var itervals = new Interval[A.Length];
for (int i = 0; i < A.Length; i++)
{
// use long to avoid data overflow (eg. int.MaxValue + 1)
long radius = A[i];
itervals[i] = new Interval()
{
Left = i - radius,
Right = i + radius
};
}
itervals = itervals.OrderBy(i => i.Left).ToArray();
int result = 0;
for (int i = 0; i < itervals.Length; i++)
{
var right = itervals[i].Right;
for (int j = i + 1; j < itervals.Length && itervals[j].Left <= right; j++)
{
result++;
if (result > 10000000)
{
return -1;
}
}
}
return result;
}
}
答案 15 :(得分:1)
这是一种红宝石解决方案,在编码方面得分为100/100。我现在正在发布它,因为我发现很难按照已经发布的ruby回答。
def solution(a)
end_points = []
a.each_with_index do |ai, i|
end_points << [i - ai, i + ai]
end
end_points = end_points.sort_by { |points| points[0]}
intersecting_pairs = 0
end_points.each_with_index do |point, index|
lep, hep = point
pairs = bsearch(end_points, index, end_points.size - 1, hep)
return -1 if 10000000 - pairs + index < intersecting_pairs
intersecting_pairs += (pairs - index)
end
return intersecting_pairs
end
# This method returns the maximally appropriate position
# where the higher end-point may have been inserted.
def bsearch(a, l, u, x)
if l == u
if x >= a[u][0]
return u
else
return l - 1
end
end
mid = (l + u)/2
# Notice that we are searching in higher range
# even if we have found equality.
if a[mid][0] <= x
return bsearch(a, mid+1, u, x)
else
return bsearch(a, l, mid, x)
end
end
答案 16 :(得分:0)
这是我在Python中的干净解决方案(无需导入库)。这种逻辑可以适应任何其他编程语言。
我的Codility为100%-时间:O(Nlog(N))-空间:O(N)
希望对您有帮助。
def solution(A):
start, end = [], []
for i, val in enumerate(A):
start.append(i-val)
end.append(i+val)
start.sort()
end.sort()
count, currCircles, aux1, aux2 = 0, 0, 0, 0
while aux1 != len(start) and aux2 != len(end):
if aux1 < len(start) and start[aux1] <= end[aux2]:
count += currCircles
currCircles +=1
aux1 +=1
if currCircles > 10000000:
return -1
else:
currCircles -=1
aux2 +=1
return count
答案 17 :(得分:0)
所以,我在 Scala 中进行了这个测试,我想在这里分享我的例子。我要解决的想法是:
提取数组上每个位置左右两侧的界限。
A[0] = 1 --> (0-1, 0+1) = A0(-1, 1)
A[1] = 5 --> (1-5, 1+5) = A1(-4, 6)
A[2] = 2 --> (2-2, 2+2) = A2(0, 4)
A[3] = 1 --> (3-1, 3+1) = A3(2, 4)
A[4] = 4 --> (4-4, 4+4) = A4(0, 8)
A[5] = 0 --> (5-0, 5+0) = A5(5, 5)
检查任意两个位置是否有交点
(A0_0 >= A1_0 AND A0_0 <= A1_1) OR // intersection
(A0_1 >= A1_0 AND A0_1 <= A1_1) OR // intersection
(A0_0 <= A1_0 AND A0_1 >= A1_1) // one circle contain inside the other
如果这两项检查中的任何一项为真,则计算一个交叉点。
object NumberOfDiscIntersections {
def solution(a: Array[Int]): Int = {
var count: Long = 0
for (posI: Long <- 0L until a.size) {
for (posJ <- (posI + 1) until a.size) {
val tupleI = (posI - a(posI.toInt), posI + a(posI.toInt))
val tupleJ = (posJ - a(posJ.toInt), posJ + a(posJ.toInt))
if ((tupleI._1 >= tupleJ._1 && tupleI._1 <= tupleJ._2) ||
(tupleI._2 >= tupleJ._1 && tupleI._2 <= tupleJ._2) ||
(tupleI._1 <= tupleJ._1 && tupleI._2 >= tupleJ._2)) {
count += 1
}
}
}
count.toInt
}
}
答案 18 :(得分:0)
这就是我所做的...它提供100%的性能和93%的正确性(因为一项测试“算术溢出测试”失败了。
public static int NumberOfDiscIntersections(int[] A)
{
int[] leftEdges = new int[A.Length];
int[] rightEdges = new int[A.Length];
int openDisc = 0;
int intersect = 0;
int leftEdgeIndex = 0;
for (int i = 0; i < A.Length; i++)
{
leftEdges[i] = i - A[i];
rightEdges[i] = i + A[i];
}
Array.Sort(leftEdges);
Array.Sort(rightEdges);
for (int j = 0; j < rightEdges.Length; j++)
{
for (int i = leftEdgeIndex; i < leftEdges.Length; i++)
{
if (leftEdges[i] <= rightEdges[j])
{
intersect += openDisc;
openDisc += 1;
leftEdgeIndex += 1;
}
else
{
openDisc -= 1;
break;
}
if (intersect > 10000000) return -1;
}
if(leftEdgeIndex == leftEdges.Length)
{
break; //All Left Edges are opened, So all Intersect calculated
}
}
return intersect;
}
答案 19 :(得分:0)
花费O(N * log(N))时间和O(N)空间的Javascript解决方案。
<input type="datetime-local" class="form-control" value="{{ $new_date }}">
答案 20 :(得分:0)
这是O(N)时间O(N)空间的解决方案。 无需排序。 该解决方案的Codility得分为100%。
function solution(A) {
// write your code in JavaScript (Node.js 8.9.4)
let totalUniquePairs = 0;
if (A.length === 0) return 0;
// array contain counts of how many circles begin at that index
const opens = new Array(A.length).fill(0);
// array containg counts of how many circles stop at that index
const closes = new Array(A.length).fill(0);
// populate the open/closes
for (let i = 0; i < A.length; ++i) {
const radius = A[i];
// keep this within the bounds of the array
const opensAt = Math.max(0, i - radius);
const closesAt = Math.min(A.length - 1, i + radius);
++closes[closesAt];
++opens[opensAt];
}
// operate in sort of a stack fashion
let overlapping = 0;
for (let i = 0; i < A.length; ++i) {
const opening = opens[i];
const closing = closes[i];
overlapping += opening;
if (closing <= 0) continue; // no closing, no new pairs
// naive way
// for (let j = 0; j < closing; ++j) {
// // overlapping - 1 = possible unique pairs here
// totalUniquePairs += overlapping - 1;
// if (totalUniquePairs > 10000000) return -1;
// overlapping -= 1;
// }
// optimized way
// summation pattern from 1 to some number k
// closes = 3 => totalUniquePairs += (overlapping - 1) + (overlapping - 2) + (overlapping - 3);
// ^ can be simplified as totalUniquePairs += (overlapping * k) - (k * (k + 1) / 2);
// https://en.wikipedia.org/wiki/1_%2B_2_%2B_3_%2B_4_%2B_%E2%8B%AF
totalUniquePairs += (overlapping * closing) - (closing * (closing + 1) / 2);
if (totalUniquePairs > 10000000) return -1;
overlapping -= closing;
}
return totalUniquePairs;
}
这种算法的工作方式是通过在要处理的索引处跟踪您正在处理的相交圆的数量。
当闭合圆时,您正在跟踪,您可以计算闭合圆和相交圆形成的唯一对的数量。唯一对的数量是当前相交圆的数量-1。然后,U从正在索引处跟踪的相交圆的数量中删除该圆,然后可以对在该索引处闭合的每个圆重复此模式。
这类似于在需要处理括号时弹出需要在堆栈中处理的方程式。
所以我们只需要为两件事花费内存:
答案 21 :(得分:0)
与其他答案(C ++)类似,尽管略有不同,但简短且解释清楚。时空都是线性的,而codility则是100%。
我们首先定义以下规则:
因此,在这段代码中,我们首先要确定在每个位置(0
至A.size() - 1
)上开始和结束的光盘数量。然后,我们通过以上公式更新交点。为了正确计算点3的公式,更新openDiscs
计数器很重要。
int solution(vector<int> &A) {
// count start/end points at each position
std::vector<size_t> starts(A.size(), 0);
std::vector<size_t> ends(A.size(), 0);
for (size_t idx = 0; idx < A.size(); ++idx)
{
// make sure not to have overflow here
size_t s = std::max<int>(0, idx - A[idx]);
size_t e = std::min<size_t>(A.size() - 1, idx + A[idx]);
++starts[s];
++ends[e];
}
// starts[idx] is a counter which indicates how many discs have their uttermost left point at idx
// ends[idx] is a counter which indicates how many discs have their uttermost right point at idx
// loop over lines and count intersections (make sure no overflow)
unsigned long int openDiscs = 0;
unsigned long int intersections = 0;
for (size_t idx = 0; idx < A.size(); ++idx)
{
// intersections due to newly opened discs (point 1)
intersections += starts[idx] * (starts[idx] - 1) / 2;
// intersections due to previously opened discs (point 2, 3)
intersections += openDiscs * starts[idx];
// update open discs
openDiscs += starts[idx] - ends[idx];
if (intersections > 10000000) return -1;
}
return intersections;
}
答案 22 :(得分:0)
如果将这些光盘画在纸上,则可以直观地假定它是按每个光盘的左端排序的。对于每张光盘,请查看右端在其他光盘上的延伸量,即-与其他光盘的左端相交并在此处停止检查。这样的停止节省了我们在O(n * n)最琐碎的解决方案上花费的时间,而节省了类似O(n * log(n))的时间。效率不如这里的某些O(n)解决方案高,但是它是一个简单易懂的代码,对于100%的Codility提交足够有效。解决此问题时,我确实从noisyboiler和GnomeDePlume
的帖子中汲取了灵感语言是Java语言
function solution(A) {
//for each disk, create an array of objects containing left and right ends, then sort it by the left end.
const B = A.map((a, i) => ({ left: i - a, right: i + a })).sort((a, b) => a.left - b.left)
let count = 0
//index i is the disk we are testing intersection with any disc j
for (let i = 0; i < B.length - 1; i++) {
for (let j = i + 1; j < B.length; j++) {
if (B[i].right >= B[j].left) {
count++;
//this is just an explicit condition for the codility task
if (count > 10000000) return -1
}
else break;
//since the array is sorted by the left ends, we know that we won't find any disk that the right side of disc i would reach
}
}
return count
}
答案 23 :(得分:0)
基于此视频https://www.youtube.com/watch?v=HV8tzIiidSw的Javascript解决方案100/100
function sortArray(A) {
return A.sort((a, b) => a - b)
}
function getDiskPoints(A) {
const diskStarPoint = []
const diskEndPoint = []
for(i = 0; i < A.length; i++) {
diskStarPoint.push(i - A[i])
diskEndPoint.push(i + A[i])
}
return {
diskStarPoint: sortArray(diskStarPoint),
diskEndPoint: sortArray(diskEndPoint)
};
}
function solution(A) {
const { diskStarPoint, diskEndPoint } = getDiskPoints(A)
let index = 0;
let openDisks = 0;
let intersections = 0;
for(i = 0; i < diskStarPoint.length; i++) {
while(diskStarPoint[i] > diskEndPoint[index]) {
openDisks--
index++
}
intersections += openDisks
openDisks++
}
return intersections > 10000000 ? -1 : intersections
}
答案 24 :(得分:0)
golang solution,因为codility仅支持v1.4以上的版本,因此我们必须手动实现Sorter接口才能对2元组数组进行排序;
package solution
// you can also use imports, for example:
// import "fmt"
import "sort"
// you can write to stdout for debugging purposes, e.g.
// fmt.Println("this is a debug message")
type Circle struct {
left, right int
}
type CircleSorter []*Circle
func (cs CircleSorter) Len() int {
return len(cs)
}
func (cs CircleSorter) Swap(i, j int) {
cs[i], cs[j] = cs[j], cs[i]
}
func (cs CircleSorter) Less(i, j int) bool {
return cs[i].left < cs[j].left
}
func BiSecRight(data []*Circle, target int) int {
return sort.Search(len(data), func(i int) bool {
return data[i].left > target
})
}
func Solution(A []int) int {
data := make([]*Circle, len(A))
for i := 0; i < len(A); i++ {
data[i] = &Circle{
left: i - A[i],
right: i + A[i],
}
}
sort.Sort(CircleSorter(data))
count := 0
for i, v := range data {
count += BiSecRight(data, v.right) - 1 - i
}
if count > 10000000 {
count = -1
}
return count
}
答案 25 :(得分:0)
这在c#中得到100/100
class CodilityDemo3
{
public static int GetIntersections(int[] A)
{
if (A == null)
{
return 0;
}
int size = A.Length;
if (size <= 1)
{
return 0;
}
List<Line> lines = new List<Line>();
for (int i = 0; i < size; i++)
{
if (A[i] >= 0)
{
lines.Add(new Line(i - A[i], i + A[i]));
}
}
lines.Sort(Line.CompareLines);
size = lines.Count;
int intersects = 0;
for (int i = 0; i < size; i++)
{
Line ln1 = lines[i];
for (int j = i + 1; j < size; j++)
{
Line ln2 = lines[j];
if (ln2.YStart <= ln1.YEnd)
{
intersects += 1;
if (intersects > 10000000)
{
return -1;
}
}
else
{
break;
}
}
}
return intersects;
}
}
public class Line
{
public Line(double ystart, double yend)
{
YStart = ystart;
YEnd = yend;
}
public double YStart { get; set; }
public double YEnd { get; set; }
public static int CompareLines(Line line1, Line line2)
{
return (line1.YStart.CompareTo(line2.YStart));
}
}
}
答案 26 :(得分:0)
感谢Falk的好主意!这是一个利用稀疏性的ruby实现。
def int(a)
event = Hash.new{|h,k| h[k] = {:start => 0, :stop => 0}}
a.each_index {|i|
event[i - a[i]][:start] += 1
event[i + a[i]][:stop ] += 1
}
sorted_events = (event.sort_by {|index, value| index}).map! {|n| n[1]}
past_start = 0
intersect = 0
sorted_events.each {|e|
intersect += e[:start] * (e[:start]-1) / 2 +
e[:start] * past_start
past_start += e[:start]
past_start -= e[:stop]
}
return intersect
end
puts int [1,1]
puts int [1,5,2,1,4,0]
答案 27 :(得分:0)
O(N * logN)100%/ 100%
// you can also use imports, for example:
import java.util.*;
// you can write to stdout for debugging purposes, e.g.
// System.out.println("this is a debug message");
class Solution {
public int solution(int[] A) {
long[] startPositionList = new long[A.length];
long[] finishPositionList = new long[A.length];
for (int i = 0; i < A.length; i++) {
// (long), because otherwise number 2,147,483,647 will overflow
startPositionList[i] = (long)i - A[i];
finishPositionList[i] = (long)i + A[i];
}
Arrays.sort(startPositionList);
Arrays.sort(finishPositionList);
int count = 0;
int multiplier = 0;
int startIndex = 0;
int finishIndex = 0;
// After we passed through all start positions, our solution won't change, hence we can stop the loop
while (startIndex < A.length) {
if (startPositionList[startIndex] > finishPositionList[finishIndex]) {
// Finish position is next smallest
multiplier--;
finishIndex++;
} else {
// Start position is next smallest or is equal to finish position
count += multiplier;
multiplier++;
startIndex++;
// There is a condition to return -1 if count is bigger than 1e7
if (count > (int)1e7) {
return -1;
}
}
}
return count;
}
}
答案 28 :(得分:0)
const endpoints = [];
A.map((val, index) => {
endpoints.push([index - val, 'S']);
endpoints.push([index + val, 'E']);
});
endpoints.sort((a, b) => {
if (a[0] < b[0]) {
return -1;
}
if (a[0] > b[0]) {
return 1;
}
if (a[0] === b[0] && a[1] === 'S')
return -1;
else
return 1;
});
let count = 0;
let intersections = 0;
let point = [];
const length = endpoints.length;
for (let i = 0; i < length; i++) {
point = endpoints[i];
if (point[1] === 'S') {
count += intersections;
intersections += 1
} else {
intersections -= 1;
}
if (intersections > 10e6)
return -1;
}
return count;
答案 29 :(得分:0)
Aryabhatta(二进制搜索解决方案)所描述的100/100 C#实现。
using System;
class Solution {
public int solution(int[] A)
{
return IntersectingDiscs.Execute(A);
}
}
class IntersectingDiscs
{
public static int Execute(int[] data)
{
int counter = 0;
var intervals = Interval.GetIntervals(data);
Array.Sort(intervals); // sort by Left value
for (int i = 0; i < intervals.Length; i++)
{
counter += GetCoverage(intervals, i);
if(counter > 10000000)
{
return -1;
}
}
return counter;
}
private static int GetCoverage(Interval[] intervals, int i)
{
var currentInterval = intervals[i];
// search for an interval starting at currentInterval.Right
int j = Array.BinarySearch(intervals, new Interval { Left = currentInterval.Right });
if(j < 0)
{
// item not found
j = ~j; // bitwise complement (see Array.BinarySearch documentation)
// now j == index of the next item larger than the searched one
j = j - 1; // set index to the previous element
}
while(j + 1 < intervals.Length && intervals[j].Left == intervals[j + 1].Left)
{
j++; // get the rightmost interval starting from currentInterval.Righ
}
return j - i; // reduce already processed intervals (the left side from currentInterval)
}
}
class Interval : IComparable
{
public long Left { get; set; }
public long Right { get; set; }
// Implementation of IComparable interface
// which is used by Array.Sort().
public int CompareTo(object obj)
{
// elements will be sorted by Left value
var another = obj as Interval;
if (this.Left < another.Left)
{
return -1;
}
if (this.Left > another.Left)
{
return 1;
}
return 0;
}
/// <summary>
/// Transform array items into Intervals (eg. {1, 2, 4} -> {[-1,1], [-1,3], [-2,6]}).
/// </summary>
public static Interval[] GetIntervals(int[] data)
{
var intervals = new Interval[data.Length];
for (int i = 0; i < data.Length; i++)
{
// use long to avoid data overflow (eg. int.MaxValue + 1)
long radius = data[i];
intervals[i] = new Interval
{
Left = i - radius,
Right = i + radius
};
}
return intervals;
}
}
答案 30 :(得分:0)
以下是@Aryabhatta在科特林接受的答案的实现,因此所有功劳归@Aryabhatta
fun calculateDiscIntersections(A: Array<Int>): Int {
val MAX_PAIRS_ALLOWED = 10_000_000L
//calculate startX and endX for each disc
//as y is always 0 so we don't care about it. We only need X
val ranges = Array(A.size) { i ->
calculateXRange(i, A[i])
}
//sort Xranges by the startX
ranges.sortBy { range ->
range.start
}
val starts = Array(ranges.size) {index ->
ranges[index].start
}
var count = 0
for (i in 0 until ranges.size) {
val checkRange = ranges[i]
//find the right most disc whose start is less than or equal to end of current disc
val index = bisectRight(starts, checkRange.endInclusive, i)
//the number of discs covered by this disc are:
//count(the next disc/range ... to the last disc/range covered by given disc/range)
//example: given disc index = 3, last covered (by given disc) disc index = 5
//count = 5 - 3 = 2
//because there are only 2 discs covered by given disc
// (immediate next disc with index 4 and last covered disc at index 5)
val intersections = (index - i)
//because we are only considering discs intersecting/covered by a given disc to the right side
//and ignore any discs that are intersecting on left (because previous discs have already counted those
// when checking for their right intersects) so this calculation avoids any duplications
count += intersections
if (count > MAX_PAIRS_ALLOWED) {
return -1
}
}
return if (count > MAX_PAIRS_ALLOWED) {
-1
} else {
count
}
}
private fun calculateXRange(x: Int, r: Int): LongRange {
val minX = x - r.toLong()
val maxX = x + r.toLong()
return LongRange(minX, maxX)
}
fun bisectRight(array: Array<Long>, key: Long, arrayStart: Int = 0): Int {
var start = arrayStart
var end = array.size - 1
var bisect = start
while (start <= end) {
val mid = Math.ceil((start + end) / 2.0).toInt()
val midValue = array[mid]
val indexAfterMid = mid + 1
if (key >= midValue) {
bisect = mid
}
if (key >= midValue && (indexAfterMid > end || key < array[indexAfterMid])) {
break
} else if (key < midValue) {
end = mid - 1
} else {
start = mid + 1
}
}
return bisect
}
Codility Solution得分为100%。
答案 31 :(得分:0)
这里已经有很多不错的答案,包括已接受答案的出色解释。但是,我想指出一点关于Python语言中实现细节的观察。
最初,我提出了以下所示的解决方案。我原本希望在有O(N*log(N))
个迭代的单个for循环时获得N
的时间复杂度,并且每个迭代执行一次最多需要log(N)
的二进制搜索。
def solution(a):
import bisect
if len(a) <= 1:
return 0
cuts = [(c - r, c + r) for c, r in enumerate(a)]
cuts.sort(key=lambda pair: pair[0])
lefts, rights = zip(*cuts)
n = len(cuts)
total = 0
for i in range(n):
r = rights[i]
pos = bisect.bisect_right(lefts[i+1:], r)
total += pos
if total > 10e6:
return -1
return total
但是,我得到O(N**2)
和超时失败。你看到这里有什么问题吗?正确,此行:
pos = bisect.bisect_right(lefts[i+1:], r)
在这一行中,您实际上是在获取原始列表的一份副本,以将其传递给二进制搜索功能,这完全破坏了所提出的解决方案的效率!它使您的代码更加简洁(即,您无需编写pos - i - 1
),但是却严重影响了性能。因此,如上所示,解决方案应为:
def solution(a):
import bisect
if len(a) <= 1:
return 0
cuts = [(c - r, c + r) for c, r in enumerate(a)]
cuts.sort(key=lambda pair: pair[0])
lefts, rights = zip(*cuts)
n = len(cuts)
total = 0
for i in range(n):
r = rights[i]
pos = bisect.bisect_right(lefts, r)
total += (pos - i - 1)
if total > 10e6:
return -1
return total
似乎有时人们可能会急于制作切片和副本,因为Python允许您如此轻松地完成它:)可能不是一个很好的见解,但对我来说,这是一个很好的课程,更多地关注这些“技术性的”,将想法和算法转化为实际解决方案的时刻。
答案 32 :(得分:0)
以下是关于codility得分为100的PHP代码:
$sum=0;
//One way of cloning the A:
$start = array();
$end = array();
foreach ($A as $key=>$value)
{
$start[]=0;
$end[]=0;
}
for ($i=0; $i<count($A); $i++)
{
if ($i<$A[$i])
$start[0]++;
else
$start[$i-$A[$i]]++;
if ($i+$A[$i] >= count($A))
$end[count($A)-1]++;
else
$end[$i+$A[$i]]++;
}
$active=0;
for ($i=0; $i<count($A);$i++)
{
$sum += $active*$start[$i]+($start[$i]*($start[$i]-1))/2;
if ($sum>10000000) return -1;
$active += $start[$i]-$end[$i];
}
return $sum;
但是我不理解逻辑。这只是从上面转换的C ++代码。伙计们,你能详细说明你在这做什么吗?
答案 33 :(得分:0)
C# 100/100 ,时间复杂度O(N*log(N))
,空间复杂度O(N)
。
主要观点:
true
表示&#34;打开&#34;而false
表示&#34;关闭&#34;间隔。_
public int solution(int[] A)
{
var sortedStartPoints = A.Select((value, index) => (long)index-value).OrderBy(i => i).ToArray();
var sortedEndPoints = A.Select((value, index) => (long)index+value).OrderBy(i => i).ToArray();
// true - increment, false - decrement, null - stop
var points = new bool?[2*A.Length];
// merge arrays
for(int s=0, e=0, p=0; p < points.Length && s < sortedStartPoints.Length; p++)
{
long startPoint = sortedStartPoints[s];
long endPoint = sortedEndPoints[e];
if(startPoint <= endPoint)
{
points[p] = true;
s++;
}
else
{
points[p] = false;
e++;
}
}
int result = 0;
int opened = 0;
// calculate intersections
foreach(bool? p in points.TakeWhile(_ => _.HasValue))
{
if(result > 10000000)
return -1;
if(p == true)
{
result += opened;
opened++;
}
else
{
opened--;
}
}
return result;
}
答案 34 :(得分:0)
红宝石溶液。得分100%。
def solution(a)
# write your code in Ruby 2.2
open = Hash.new
close = Hash.new
(0..(a.length-1)).each do |c|
r = a[c]
open[ c-r ] ? open[ c-r ]+=1 : open[ c-r ]=1
close[ c+r ] ? close[ c+r ]+=1 : close[ c+r ]=1
end
open_now = 0
intersections = 0
open.merge(close).keys.sort.each do |v|
intersections += (open[v]||0)*open_now
open_now += (open[v]||0) - (close[v]||0)
if(open[v]||0)>1
# sum the intersections of only newly open discs
intersections += (open[v]*(open[v]-1))/2
return -1 if intersections > 10000000
end
end
intersections
end
答案 35 :(得分:0)
C#解决方案100/100
using System.Linq;
class Solution
{
private struct Interval
{
public Interval(long @from, long to)
{
From = @from;
To = to;
}
public long From { get; }
public long To { get; }
}
public int solution(int[] A)
{
int result = 0;
Interval[] intervals = A.Select((value, i) =>
{
long iL = i;
return new Interval(iL - value, iL + value);
})
.OrderBy(x => x.From)
.ToArray();
for (int i = 0; i < intervals.Length; i++)
{
for (int j = i + 1; j < intervals.Length && intervals[j].From <= intervals[i].To; j++)
result++;
if (result > 10000000)
return -1;
}
return result;
}
}
答案 36 :(得分:0)
我在斯威夫特的回答;获得100%的分数。
import Glibc
struct Interval {
let start: Int
let end: Int
}
func bisectRight(intervals: [Interval], end: Int) -> Int {
var pos = -1
var startpos = 0
var endpos = intervals.count - 1
if intervals.count == 1 {
if intervals[0].start < end {
return 1
} else {
return 0
}
}
while true {
let currentLength = endpos - startpos
if currentLength == 1 {
pos = startpos
pos += 1
if intervals[pos].start <= end {
pos += 1
}
break
} else {
let middle = Int(ceil( Double((endpos - startpos)) / 2.0 ))
let middlepos = startpos + middle
if intervals[middlepos].start <= end {
startpos = middlepos
} else {
endpos = middlepos
}
}
}
return pos
}
public func solution(inout A: [Int]) -> Int {
let N = A.count
var nIntersections = 0
// Create array of intervals
var unsortedIntervals: [Interval] = []
for i in 0 ..< N {
let interval = Interval(start: i-A[i], end: i+A[i])
unsortedIntervals.append(interval)
}
// Sort array
let intervals = unsortedIntervals.sort {
$0.start < $1.start
}
for i in 0 ..< intervals.count {
let end = intervals[i].end
var count = bisectRight(intervals, end: end)
count -= (i + 1)
nIntersections += count
if nIntersections > Int(10E6) {
return -1
}
}
return nIntersections
}
答案 37 :(得分:0)
#include <stdio.h>
#include <stdlib.h>
void sortPairs(int bounds[], int len){
int i,j, temp;
for(i=0;i<(len-1);i++){
for(j=i+1;j<len;j++){
if(bounds[i] > bounds[j]){
temp = bounds[i];
bounds[i] = bounds[j];
bounds[j] = temp;
temp = bounds[i+len];
bounds[i+len] = bounds[j+len];
bounds[j+len] = temp;
}
}
}
}
int adjacentPointPairsCount(int a[], int len){
int count=0,i,j;
int *bounds;
if(len<2) {
goto toend;
}
bounds = malloc(sizeof(int)*len *2);
for(i=0; i< len; i++){
bounds[i] = i-a[i];
bounds[i+len] = i+a[i];
}
sortPairs(bounds, len);
for(i=0;i<len;i++){
int currentBound = bounds[i+len];
for(j=i+1;a[j]<=currentBound;j++){
if(count>100000){
count=-1;
goto toend;
}
count++;
}
}
toend:
free(bounds);
return count;
}
答案 38 :(得分:0)
这是一个两遍C ++解决方案,不需要任何库,二进制搜索,排序等。
int solution(vector<int> &A) {
#define countmax 10000000
int count = 0;
// init lower edge array
vector<int> E(A.size());
for (int i = 0; i < (int) E.size(); i++)
E[i] = 0;
// first pass
// count all lower numbered discs inside this one
// mark lower edge of each disc
for (int i = 0; i < (int) A.size(); i++)
{
// if disc overlaps zero
if (i - A[i] <= 0)
count += i;
// doesn't overlap zero
else {
count += A[i];
E[i - A[i]]++;
}
if (count > countmax)
return -1;
}
// second pass
// count higher numbered discs with edge inside this one
for (int i = 0; i < (int) A.size(); i++)
{
// loop up inside this disc until top of vector
int jend = ((int) E.size() < (long long) i + A[i] + 1 ?
(int) E.size() : i + A[i] + 1);
// count all discs with edge inside this disc
// note: if higher disc is so big that edge is at or below
// this disc center, would count intersection in first pass
for (int j = i + 1; j < jend; j++)
count += E[j];
if (count > countmax)
return -1;
}
return count;
}
答案 39 :(得分:0)
Codility中的100%得分。
public int solution(int[] A)
{
long result = 0;
Dictionary<long, int> dps = new Dictionary<long, int>();
Dictionary<long, int> dpe = new Dictionary<long, int>();
for (int i = 0; i < A.Length; i++)
{
Inc(dps, Math.Max(0, i - A[i]));
Inc(dpe, Math.Min(A.Length - 1, i + A[i]));
}
long t = 0;
for (int i = 0; i < A.Length; i++)
{
int value;
if (dps.TryGetValue(i, out value))
{
result += t * value;
result += value * (value - 1) / 2;
t += value;
if (result > 10000000)
return -1;
}
dpe.TryGetValue(i, out value);
t -= value;
}
return (int)result;
}
private static void Inc(Dictionary<long, int> values, long index)
{
int value;
values.TryGetValue(index, out value);
values[index] = ++value;
}
答案 40 :(得分:0)
以上Java中所述的实现:
public class DiscIntersectionCount {
public int number_of_disc_intersections(int[] A) {
int[] leftPoints = new int[A.length];
for (int i = 0; i < A.length; i++) {
leftPoints[i] = i - A[i];
}
Arrays.sort(leftPoints);
// System.out.println(Arrays.toString(leftPoints));
int count = 0;
for (int i = 0; i < A.length - 1; i++) {
int rpoint = A[i] + i;
int rrank = getRank(leftPoints, rpoint);
//if disk has sifnificant radius, exclude own self
if (rpoint > i) rrank -= 1;
int rank = rrank;
// System.out.println(rpoint+" : "+rank);
rank -= i;
count += rank;
}
return count;
}
public int getRank(int A[], int num) {
if (A==null || A.length == 0) return -1;
int mid = A.length/2;
while ((mid >= 0) && (mid < A.length)) {
if (A[mid] == num) return mid;
if ((mid == 0) && (A[mid] > num)) return -1;
if ((mid == (A.length - 1)) && (A[mid] < num)) return A.length;
if (A[mid] < num && A[mid + 1] >= num) return mid + 1;
if (A[mid] > num && A[mid - 1] <= num) return mid - 1;
if (A[mid] < num) mid = (mid + A.length)/2;
else mid = (mid)/2;
}
return -1;
}
public static void main(String[] args) {
DiscIntersectionCount d = new DiscIntersectionCount();
int[] A =
//{1,5,2,1,4,0}
//{0,0,0,0,0,0}
// {1,1,2}
{3}
;
int count = d.number_of_disc_intersections(A);
System.out.println(count);
}
}
答案 41 :(得分:-1)
Aryabhattas的JavaScript版本。我已经改变了一点,使它更具JS和更高效的性能,并添加了注释来解释算法的作用。希望这会有所帮助。
function solution(A) {
var result = 0,
len = A.length,
dps = new Array(len).fill(0),
dpe = new Array(len).fill(0),
i,
active = len - 1,
s,
e;
for (i = 0; i < len; i++) {
// adds to the begin array how many discs begin at the specific position given
if (i > A[i])
s = i - A[i];
else
s = 0;
// adds to the end array the amount of discs that end at this specific position
if (active - i > A[i])
e = i + A[i]
else
e = active;
// a disc always begins and ends somewhere, s and e are the starting and ending positions where this specific disc for the element in A at position i reside
dps[s] += 1;
dpe[e] += 1;
}
// no discs are active as the algorithm must calculate the overlaps first, then the discs can be made active, hence why it begins with 0 active
active = 0;
for (i = 0; i < len; i++) {
if (dps[i] > 0) {
// new discs has entered the zone, multiply it with the current active discs as the new discs now overlap with the older active ones
result += active * dps[i];
// new discs must also be counted against each other and not just the ones which were active prior
result += dps[i] * (dps[i] - 1) / 2;
// assignment rules
if (10000000 < result)
return -1;
// add new discs to the active list that have started at this position
active += dps[i];
}
// remove discs as they have ended at this position
active -= dpe[i];
}
// return the result
return result;
}
var A = [1, 5, 2, 1, 4, 0]; // should return 11
console.log(solution(A));
答案 42 :(得分:-1)
下面的Java语言解决方案将获得100/100
if (A == null || A.length < 2) {
return 0;
}
int[] B = Arrays.copyOf(A, A.length);
Arrays.sort(B);
int biggest = B[A.length - 1];
int intersections = 0;
for (int i = 0; i < A.length; i++) {
for (int j = i + 1; j < A.length; j++) {
if (j - biggest > i + A[i]) {
break;
}
if (j - A[j] <= i + A[i]) {
intersections++;
}
if (intersections > 10000000) {
return -1;
}
}
}
return intersections;