4.4 NumberOfDiscIntersections

来源:互联网 发布:三国乱世盘古挂机软件 编辑:程序博客网 时间:2024/05/24 06:49

Compute intersections between sequence of discs.
数组A[i]保存以i为圆点,A[i]为半径的圆。求多少对圆至少有一个共同点。
Given an array A of N integers, we draw N discs in a 2D plane such that the I-th disc is centered on (0,I) and has a radius of A[I]. We say that the J-th disc and K-th disc intersect if J ≠ K and J-th and K-th discs have at least one common point.
Write a function:
class Solution { public int solution(int[] A); }
that, given an array A describing N discs as explained above, returns the number of pairs of intersecting discs. For example, given N=6 and:
A[0] = 1 A[1] = 5 A[2] = 2
A[3] = 1 A[4] = 4 A[5] = 0
intersecting discs appear in eleven pairs of elements:
0 and 1,
0 and 2,
0 and 4,
1 and 2,
1 and 3,
1 and 4,
1 and 5,
2 and 3,
2 and 4,
3 and 4,
4 and 5.
so the function should return 11.
The function should return −1 if the number of intersecting pairs exceeds 10,000,000.
Assume that:
N is an integer within the range [0..100,000];
each element of array A is an integer within the range [0..2,147,483,647].
Complexity:
expected worst-case time complexity is O(N*log(N));
expected worst-case space complexity is O(N), beyond input storage (not counting the storage required for input arguments).

Solution

class Solution {    class Node implements Comparable<Node>{        public long left;        public long right;        public Node(long left, long right){            this.left = left;            this.right = right;        }        public int compareTo(Node node){            Long obj1 = new Long(this.right);            Long obj2 = new Long(node.right);            return obj1.compareTo(obj2);        }    }    public int solution(int[] A) {        // write your code in Java SE 8        Node[] nodes = new Node[A.length];        for(int i=0; i<A.length; i++){            Node node = new Node(i-(long)A[i],i+(long)A[i]);            nodes[i]=node;        }        Arrays.sort(nodes);        int count=0;        for(int i= A.length-1; i>0; i--){            long left = nodes[i].left;            int pos = Arrays.binarySearch(nodes,new Node(0,left));//compare left to right            if(pos >= 0) {                while (pos - 1 >= 0) {                    if (nodes[pos-1].right == left){                        pos--;                    }                    else break;                }                count+=(i-pos);            }            else{                pos = Math.abs(pos+1);                count+=(i-pos);            }                  }        if(count<0 || count>10000000) return -1;        return count;    }}

看到题目第一个反应是线段树,创建树时经过的父节点cover+1,最后遍历树累加得到结果。实现后发现左节点和右节点也有可能满足条件。
又想到将线段按照左边界排序。 从前向后扫描如果第i个元素的右边界right[i]扫描数组,如果left[k]<=right[i], 两者之接的线段(i,K]都与i相交。
或者将线段按照右边界排序。 从后向前扫描。假设第i个元素的左边界left[i]扫描数组,如果left[i]<=right[k], 两者之接的线段(k,i]都与i相交。
使用Arrays.binarySearch进行数组查找重复元素时,不能保证指向重复元素的头,导致漏点。所以匹配到点后后要向前找到起始位置。
如果使用int保存left,right会溢出。还是python好啊,不用考虑溢出的问题

0 0
原创粉丝点击