Google Interview Question for Software Engineer / Developers


Country: United States




Comment hidden because of low score. Click to expand.
10
of 10 vote

rearrange them in the format of interval: [-1,1] [-4,6] ...
then the problem becomes checking overlapping intervals.
just sort them on the base of starting point and binary search each end point in the sorted list

- zyfo2 February 24, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

checking of overlapping intervals is not done using binary search. If we search the sorted list using the end point of the current disc, the range between this point and the starting point will contain discs that their start point is in that range, so they potentially intersect the current disc. But some of them may also end before the current disc end point, so they dont intersect the current disc. Therefore your algorithm is wrong, unless you check the end point of all the discs in the start-end range of the current disc, which will make this a O(n^2) time algorithm, just like the naive solution.

- gen-y-s February 28, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

I believe his answer implied that we only consider discs that start below the current disc (which can be determined in constant time). Considering discs above would count each intersection twice.

- Barry Fruitman February 28, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Obviously his algorithm only considers discs that started before the current disc, since it's iterating on the list sorted by starting points. But from those discs, how does he find which discs end after the current disc's starting point (thus intersecting the current disc). There is no way (in this algorithm) to find these discs without scanning all the discs, which would make this o(n^2).

- gen-y-s March 01, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Reread the question. Based on the question an intersection between 2 disk occurs if any points within (or on the edge) the disc is shared with any point within (or on the edge) of another disc. This is why he called it disc and not circle. Your concern only occurs if we would be interested in circumference intersection which is not the case here.

- Zythum42 March 01, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@gen-y-s The way I read it, he's iterating on the original list sorted by center, not the new list sorted by starting point. As he goes along the first list, he searches for intersecting discs in the second list. This process should take O(N log N).

Please look below for the elaboration I wrote yesterday, based on what I think he is saying.

- Barry Fruitman March 01, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@Zythum, I now understand his algorithm - it's basically for each disc, to find all the discs that overlap it.
@Barry, your explanation is not correct. The center of the disc is not relevant, only the top and bottom. Also, the order of the discs we iterate over doesn't matter in this algorithm. Therefore, it would work even if the original list wasn't ordered at all and you iterated over it to find the overlapping discs using the sorted list.
This means that zyfo's algorithm doesn't require any extra storage if you sort the original list in-place.

- gen-y-s March 01, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

I agree the location of the center of the disc is irrelevant to determining overlap, but it's a useful way to index the discs for the purposes of iteration because it guarantees we can iterate in precisely O(N) time. Plus we receive the data this way.

Keeping the original list does require more space, but that is allowed by the problem.

It's possible my explanation is incorrect because it's hard to tell what the original poster was saying, but my solution is still correct. I think there is more than one correct way to iterate over of the discs...

- Barry Fruitman March 01, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Same idea as zyfo2's.
The follwoing is my Java implementation with a simple test:

import java.util.*;

class G217
{
 public static void main(String[] args)
 {
  int[] array1 = {1, 5, 2, 1, 4, 0};
  System.out.println("result1 = " + number_of_disc_intersections(array1));
 }

 public static int number_of_disc_intersections(int[] A)
 {
  int N = A.length;
  double[] begin = new double[N];
  double[] end = new double[N];
  for (int i = 0; i < N; i++)
  {
   begin[i] = i - A[i];
   end[i] = i + A[i];
  }
  Arrays.sort(begin);

  int sum = 0;
  for (int i = 0; i < N; i++)
  {
   double e = end[i];
   int index = Arrays.binarySearch(begin, e + 0.5);
   int insert = -(index + 1);
   sum += (insert - i - 1);
   if (sum > 10000000) {return (-1);}
  }

  return sum;
 }
}

- Alva0930 March 03, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@Alva0930 Can you please explain how this equals the number of overlapping discs?

int index = Arrays.binarySearch(begin, e + 0.5);
int insert = -(index + 1);
sum += (insert - i - 1);

Thanks

- Barry Fruitman March 03, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

I've been thinking about it, and I don't think any solution that uses a binary search to find the tops and/or bottoms of discs will guarantee a worst-case complexity of O(N log N). The problem is that a binary search has a complexity of O(N) in the case where all the tops (or bottoms) overlap. Multiply this by the iteration and we have a worst-case complexity of O(N^2) for any solution that uses this approach. :(

I'm starting to think that interval trees (see below) are the way to go.

http://en.wikipedia.org/wiki/Interval_tree

- Barry Fruitman March 03, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

int index = Arrays.binarySearch(begin, e + 0.5);
int insert = -(index + 1);

These two lines are used to find how many begin points are less than or equal to the current end point.
The following is the description of the return value of Arrays.binarySearch() in JavaDoc:
Returns:
index of the search key, if it is contained in the array;
otherwise, (-(insertion point)- 1).
The insertion point is defined as the point at which the key would be inserted into the array:
the index of the first element greater than the key,
or a.length if all elements in the array are less than the specified key.
Note that this guarantees that the return value will be >= 0 if and only if the key is found.

sum += (insert - i - 1);

For a given disc(for example: A[2] = 2),
we must subtract the begin points from disc on the left(for example: A[0] = 1 and A[1] = 5) to prevent double counting,
and we alos need to subtract the disc itself(for example: A[2] = 2).
The example I used is the example of original question.
The following are the logs of execution.
You may compare the logs with the result of the example of original question.

i = 0; insert = 4; (insert - i - 1) = 3
i = 1; insert = 6; (insert - i - 1) = 4
i = 2; insert = 5; (insert - i - 1) = 2
i = 3; insert = 5; (insert - i - 1) = 1
i = 4; insert = 6; (insert - i - 1) = 1
i = 5; insert = 6; (insert - i - 1) = 0
result1 = 11

BTW, the time complexity of my Java implementation is O(N logN).

- Alva0930 March 04, 2013 | Flag
Comment hidden because of low score. Click to expand.
4
of 4 vote

This solution occupies O(n) extra space and works in O(logn), Does it sound correct?:

I write down the max and min points of the circles and store them in an array using a data structure to identify the index of each point. Then, I sort them in nlogn.

Next I iterate through the array keeping note of circle starts and ends using a hashmap and whenver a circle ends, all the circles which are enveloping it add to the number of intersections. Hence, I add them up.

import java.util.Arrays;
import java.util.HashMap;


public class Circle {

	class node implements Comparable<node>{
		int value;
		int index;
		node(int index, int value) {
			this.index = index;
			this.value = value;
		}
		public int compareTo(Circle.node o) {
			return this.value - o.value;
		}
	}
	int[] A;
	node[] B;
	Circle(int[] in) {
		this.A = in;
		B = new node[A.length*2];

		for( int i = 0 ;i < A.length; i++) {
			B[2*i] = new node(i, i - A[i]);
			B[2*i+1] = new node(i, i + A[i]);

		}
	}

	int process() {
		Arrays.sort(B);
		int sum = 0, envelopes = 0, i =0;
		HashMap<Integer, Boolean> m = new HashMap<Integer, Boolean>();
		while( i < B.length) {
			System.out.println("node " +B[i].index +" value "+ B[i].value);
			if(m.containsKey(B[i].index))
			{
				m.remove(B[i].index);
				envelopes--;
				sum += envelopes;

			}else{

				m.put(B[i].index, true);
				envelopes++;

			}
			i++;
		}
		return sum;
	}
	public static void main(String args[]) {

		int[] A = {1,5,2,1,4,0};
		Circle c = new Circle(A);
		System.out.println(c.process());
	}

}

- gururaj.kosuru February 23, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
-1
of 1 vote

First of all, you may not need to sort the index. Because, the index is already sorted. Here is the hint from the question
"
such that the I-th disc is centered on (0,I)
"

- Towhid February 23, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

I am not sorting by the index but by the value so that I have a list of all starting and ending points of the circles which is my data structure B.

- gururaj.kosuru February 24, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Could you explain what you mean by envelop? The question mentions disks that intersect, so there may be disks that are enveloped by others yet share no points. Am I missing something here?

- arthur.thompson.jr February 28, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

You mean "works in O(n log n)" , not "O(log n)", right?

- Barry Fruitman February 28, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@barry
The question specifies that an intersection between 2 circles, in this case, occurs if any point of the inner disk (not just the edge) is share with any other disk.
@Kosuru
This is the best solution around so far, a HashSet will do the map too, you are not really using that boolean value in the map.

- Zythum42 February 28, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Unfortunately looking up discs in a hash map while iterating through the list will have worst-case time of O(N^2 log N). Consider the case where ALL the discs are overlapping: they will all be in the same bucket so each lookup will take O(N)..

I do believe your algorithm has AVERAGE performance of O(N log N), though.

- Barry Fruitman February 28, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Scratch that. They can't ALL be overlapping since they're evenly spaced.

- Barry Fruitman February 28, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Unscratch that. If you're mapping on the start or end (not the center), they can all overlap.

- Barry Fruitman February 28, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@Zythum42 its any shared point, thank you.

- arthur.thompson.jr February 28, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Re-scratch that. :) I see you're using the center as your hash key. Looks good to me.

One nitpick: Arrays.sort() uses quicksort which has a worst-case complexity of O(N^2). Replacing it with mergesort or heapsort would fix that.

- Barry Fruitman February 28, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@Barry
Add, Remove and Contains provide Constant O(1) time complexity on HashSet and HashMap. However, since there are no ordering in HashMap/Set, and say we are trying to find the top Key or something like that, this is where the complexity O(N) kicks in and this is where you will favor the usage of Trees. However, there's no such logic required in the above code, unless I am missing something.

- Zythum42 February 28, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@Zythum42 Hash map operations only guarantee constant time with a perfect hash function and a big enough table. Worst-case is not constant, for example, if all the entries are identical.

However that is not an issue in this case (which is why I re-scratched my original argument).

I think we are making the same point, though. :)

- Barry Fruitman February 28, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@Barry.
Yep. Also I was under the impression that the sort method from Array Utils in Java will use the merge sort when you define your own comparator. Quicksort is used for primitive type for which no comparator definition is required... Would need to double check though.

- Anonymous February 28, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Sorry I was logged out.

- Zythum42 February 28, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@Barry : yep, missed the n in nlogn.
@Zythum : thanks for the feedback.
@Arthur: If there are two circles and one circle lies completely inside other, I used the word enveloping.

- gururaj.kosuru March 03, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

One small issue with code above:
- when two discs have start and end point in same place the order of sorting is not defined, what may cause errors in counting the correct value of intersections. To resolve the problem we can simply fix comparator to return starting points befeore ending points.

- mailing.ms April 01, 2014 | Flag
Comment hidden because of low score. Click to expand.
2
of 2 vote

1. merge start / end of all intervals in ONE array, keeping a flag that marks whether it's a start or an end.
2. sort it.
3. scan the sorted array by updating two variables, i for open intervals and c for intersection count.
- if we meet a start point, count+=i and i++
- if we meet an end point, i--.

There you go.

For the example in the question, we get a sorted array of the intervals and scan/update like this

i = 0, c = 0
-4 start, c+=0, i=1
-1 start, c+=1, i=2
0 start, c+=2, i=3
1 start c+=3, i=4
1 end i=3
2 start, c+=3, i=4
4 end, i=3
4 end, i=2
5 start, c+=2, i=3
5 end, i=2
6 end, i=1
8 end, i=0
the result is c=11.

Time complexity is O(NlgN) and space complexity is O(N).

- Franklin Pan March 17, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

a very intelligent solution i think... as the range of N and elements of A are given, we can sort in linear time and then scan the sorted list. Then it is possible to solve this problem in O(n) time complexity.

- sam April 23, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

I think it doesn't work for the following case: {100, 1}. (The answer should be 0.)

- Anonymous March 21, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Sorry, nevermind. It's OK since those are discs, not circles.

- Anonymous March 21, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

namespace ConsoleApplication1
{
    class Program
    {

        public class Interval : IComparable<Interval>
        {
            public int start;
            public int end;
            public Interval(int start, int end)
            {
                this.start = start;
                this.end = end;
            }

            public int CompareTo(Interval interval)
            {
                return this.start.CompareTo(interval.start);
            }
        }


        public static Interval[] IntArrayToIntervalArray(int[] A)
        {
            Interval[] newArray = new Interval[A.Length];
            for (int i = 0; i < A.Length; i++)
            {
                newArray[i] = new Interval(i - A[i], i + A[i]);
            }

            Array.Sort(newArray);
            return newArray;
        }

        public static int NumberOfDiscIntersections(int[] A)
        {
            Interval[] newArray = IntArrayToIntervalArray(A);
            int count = 0;
            for (int i = 0; i < A.Length; i++)
            {
                count += BinarySearchGetNumberOfIntersectingIntervals(newArray, i + 1, A.Length - 1, newArray[i]);
            }
            return count;
        }

        public static int BinarySearchGetNumberOfIntersectingIntervals(Interval[] A, int p, int r, Interval Int)
        {
            if (p <= r)
            {
                decimal x = (p + r) / 2;
                int q = (int)Math.Floor(x);
                if (A[(int)q].start < Int.end)
                {
                    return (q - p + 1) + BinarySearchGetNumberOfIntersectingIntervals(A, q + 1, r, Int);
                }
            }

            return 0;

        }


        static void Main(string[] args)
        {
            int[] A = new int[] {1,5,2,1,4,0};

            Console.WriteLine(NumberOfDiscIntersections(A));
            Console.ReadLine();
        }
    }
}

- Mauricio February 23, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

How can the expected complexity (assuming the expectation is taken over the draw of random numbers in your algorithm and not some sort of a random draw of discs) be O(n log n), when the size of the output for some trivial cases is O(n^2)?

- rajhans February 23, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
1
of 1 vote

The question only asks for the number of intersecting circles. You don't have to print out which ones intersect.

- eugene.yarovoi February 24, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@eugene.yaravoi Excellent point. It is important to understand the difference between a "find all" and "count all" problem. The former usually has higher complexity.

- Barry Fruitman March 17, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

Program:

#include <iostream>
#include <vector>

using namespace std;

struct sortFunc{
        bool operator ()(const pair<int,int>& p1, const pair<int,int>& p2) const
        { return p1.first<p2.first; }
};

int main(int argc, char* argv[])
{
        vector<int> v(argc-1, -1);
        for(int i=0; i<argc-1; i++) {
                v[i] = atoi(argv[i+1]);
        }

        vector<pair<int, int> >intVec(v.size());
        for(int i=0; i<v.size(); i++) {
                intVec[i] = make_pair(i-v[i], i+v[i]);
        }

        sort(intVec.begin(), intVec.end(), sortFunc());

        // Note : This is not n^2 but the order of results
        // This loop will break the moment we find that it cannot increment Overlaps
        int Overlaps = 0;
        for (int i=0;i<intVec.size();i++) {
                for (int j=i+1;j<intVec.size();j++) {
                        if (intVec[i].second < intVec[j].first) {
                                break;
                        } else {
                                Overlaps++;
                        }
                }
        }

        cout<< "Input is :"<<endl;
        for(int i=0; i<v.size(); i++) {
                cout<< v[i] << " ";
        }
        cout << endl;
        cout << "Overlaps : "<< Overlaps<<endl;
        return 0;
}

Output:

./a.out  1 5 2 1 4 0
Input is :
1 5 2 1 4 0 
Overlaps : 11

- SD February 24, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

This solution is O(n^2). For example, you could have concentric circles. The upper bound would still be O(n) for the inner for-loop. Hence, O(n^2).

- Jack February 25, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@Jack: I think the idea is to say the complexity is O(n log n + R) where R is the number of intersections. You're right that the number of intersections could be quadratic, but the idea is that this algorithm is reasonable if R is small.

It's true that the problem can be solved in O(n log n) overall, regardless of R.

- eugene.yarovoi February 25, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

use stl, and it is much more convenient:

bool MyCompare(pair<int,int> p1,pair<int,int> p2){return p1.first<p2.first;}
bool MyCompare2(int p1,pair<int,int> p2){return p1<p2.first;}

int NumOfIntersection(vector<int> A)
{
	int N=A.size();
	vector<pair<int,int>> P;
	for(int i=0;i<N;i++)
	{
		int start_pt=i-A[i],end_pt=i+A[i];
		P.push_back(pair<int,int>::pair(start_pt,end_pt));
	}
	sort(P.begin(),P.end(),MyCompare);
	int res=0;
	for(int i=0;i<N;i++)
	{
		vector<pair<int,int>>::iterator iter=upper_bound(P.begin()+i,P.end(),P[i].second,MyCompare2);
		iter--;
		int id=iter-P.begin();
		res+=(id-i);
	}
	return res;
}

- leehomyc February 24, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Use Interval trees. Search the page on Interval trees on Wikipedia.

- Anonymous February 24, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

You can just solve this problem with an array and some sorting. Consider that the problem can be converted to a instance of a problem where we have a list of intervals and we ask how many pairs of intervals overlap.

- eugene.yarovoi February 25, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

My idea:
a> Build an array containing left point and right point of each pixel. Each left point or right point consume on item in the array. Here is some extra trick, shift the original (left, right) ==> (left*2-1, right*2). The extra logic is making sure we can sort easily for the case that left value of some point is the same right value of some point (or even same point, in which its range is zero), in which case we need to be sure left value should be put before the right value(single point contact is till contact). And also we need to know if it is left /right value according to its value, easily.
b> merge sort the array. We need to use merge sort because worse case of quicksort is bigger than O(nlogn). The array's len is 2N, (left +right), so the merge sort will have O(2NLOG(2N)), still O(NLOGN)
c> Go through the sorted array, if it is left value, which means we found start of a new disk, so we can add preexisted disk number as total number of overlappled pair number and then increased of preexisted disk number. If it is right value, which means we found end of a new disk, we need to delete the preexisted disk number.
d> This logic bellow does not care the number limiting issue. (such 10,000,000). Some extra logic could be added for that.
e> Time complexity is O(NLOGN)+2N , still O(NLOGN). Space complexity, 2N for array, N for mergeSort, so still O(N).

- chenlc626 February 25, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Here is my code:

#include <stdio.h>

int number_of_disc_intersections(int a[], int n)
{
        int     *pNode;
        int     count, count2, count3;
        if(2>n)
                return -1;
        pNode=malloc(sizeof(int)*(n<< 1));
        if(NULL==pNode)
                return -1;
        for(count=0;count<n;count++)
        {
                count2=count<<1;
                pNode[count2]=((count-a[count])<< 1)-1; //this is make sure that
                                                             //Same value Left will be put in the before of same value of right.
                count2++;
                pNode[count2]=((count+a[count])<< 1);
        }

        mergesort(pNode, n<< 1);

        {
                for(count=0,count2=0, count3=0;count<(n<< 1);count++)
                {
                        if(pNode[count]%2)
                        {
                                //means it is left node
                                count3+=count2;
                                count2++;
                        }else
                        {
                                count2--;
                        }
                }
        }
        free(pNode);
        return count3;
}

- chenlc626 February 25, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

The code has passed test of the example shown by the interview question, also some simple cases.

- chenlc626 February 25, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

I like zyfo2's answer but it's a little terse so I'll offer my elaboration:

1. We are given a list of discs already sorted by the location of the center of disc. Create a second list of discs that is sorted by the location of the top of the disc. If we use mergesort, this operation will take O(N log N) in the worst case and O(N) space complexity in the worst case.

2. Iterate through the entire given list of discs. For every disc i, search the second list (sorted by top of disc) for the first disc whose top is located at or below the center of disc i. This is the first intersecting disk.

3. Then search for the last disc whose top is located at or above the bottom of disc i (computed as i+A[i]). This is the last intersecting disc. Both searches take O(log N) so we haven't increased the complexity.

4. The difference between the first and last disc (plus one) is the number of discs intersecting with disc i. Add this to a running total.

When we reach the end of the list, the running total will contain the solution. Note that since we are only looking for discs below disc i, we'll never count the same intersection twice.

- Barry Fruitman February 25, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Here's my solution:
1. Sort the circles by their bottom point (center - radius).
2. Initialize a min-heap that will be used to hold circles with their top point (center+radius) as key.
3. For each circle in the sorted list, compare its bottom value with the min circle on the heap, and pop from the heap all circles that their top point is lower than the current circle's bottom. The rmaining circles in the heap intersect the current circle, since their bottom point is lower than the current circle's bottom point, and their point is higher than the current circles bottom. So add the size of the heap to the count of intersecting circles. Push the current circle onto the heap.
4. Repeat step 3 for all the circles.

- gen-y-s February 28, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Here's my solution:
1. Sort the circles by their bottom point (center - radius).
2. Initialize a min-heap that will be used to hold circles with their top point (center+radius) as key.
3. For each circle in the sorted list, compare its bottom value with the min circle on the heap, and pop from the heap all circles that their top point is lower than the current circle's bottom. The rmaining circles in the heap intersect the current circle, since their bottom point is lower than the current circle's bottom point, and their point is higher than the current circles bottom. So add the size of the heap to the count of intersecting circles. Push the current circle onto the heap.
4. Repeat step 3 for all the circles.

import heapq

def disc_intersect(l):
  range_l=[(center-radius, center+radius) for (center,radius) in enumerate(l)]
  range_l.sort()
  h=[]
  tot_cnt=0
  for (start, end) in range_l:
    while len(h)>0 and start>h[0]:
      heapq.heappop(h)
    tot_cnt+=len(h)
    heapq.heappush(h, end)
  return tot_cnt

def main():
  l=[1,5,2,1,4,0]
  print disc_intersect(l)

- gen-y-s February 28, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

I got a similar question on my Google interview... and blew it. I wish I had spent more time solving this problem. Ironically, I figured out the optimal solution the next day while walking my dog. It uses DP and goes like this:

1. Sort the discs by top
2. Keep a "meta-disc" in memory and initialize it to the first disc in the sorted list. The meta-disc represents the preceding series of discs that overlap.
3. Iterate through the sorted list, from disc 2 to disc n.
4. If the top of disc i is below the bottom of the meta disc (i.e. we found a gap) re-initialize the meta-disc to disc i and proceed to the next disc.
5. However if the top of disc i is within the meta-disc, it must overlap with one of the preceding discs and we increment the overlap count.
6. Also, if the bottom of disc i is below the bottom of the meta-disc, enlarge the meta-disc by setting it's bottom to the bottom of disc i.

The meta-disc is our DP subproblem-holder. It saves us from checking every disc or searching for particular discs.

The complexity is O(n log n) due to the sort. The iterations take O(n) and don't require a binary search so each iteration takes O(1).

- Barry Fruitman March 17, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

how about this? Create another array of size N. Now for each point from 0 to N, find out how many discs reach that point. (So we init the array to 0 and for all discs d, we increment values from arr[d] to arr[d-radius(d)] and arr[d] to arr[d+radius(d)]. Now the number of overlaps at any point p = arr[p]C2 (arr[p] Choose 2).

- guru April 04, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Can some one explain how A[0] and A[1] intersect??
A[0] spans from (-1,1), and A[1] goes from (-4,6). How can these two intersect when A[0] is completely inside A[1]

- IntwPrep August 20, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Two Arrays, one with starting, one with ending points.
Sort both O N * log N
Iterate on both count the number of intersections O N.


Uses exactly O(N) extra memory and O (n * log n ) computationally.

package com.arrays;

import java.util.Arrays;
/**
 
 * @author suketu
 *
 */
public class DiscIntersections {

    
    public static void main(String[] args) {
        
        
        int[] A = {1,5,2,1,4,0};
        
        int n = getNumberOfIntersections(A);
        System.out.println(n);
        
    }

    private static int getNumberOfIntersections(int[] a) {
        
        int[] endingPoints = new int[a.length],startingPoints = a;
        for (int i = 0; i < a.length; i++) {
            if(a[i] < 0) return -1;// this is a negative radius, I don't know what to do in that case.
            endingPoints[i] = i + a[i];
            startingPoints[i] = i - a[i];
        }
        Arrays.sort(startingPoints);
        Arrays.sort(endingPoints);
        int intersections = 0;
        int currentDiscs = 0;
        for(int i = 0, j = 0; i < startingPoints.length || j < endingPoints.length; ) {
            
            if( i < startingPoints.length && startingPoints[i] <= endingPoints[j]) {
                currentDiscs++;
                i++;
            } else {
                currentDiscs--;
                intersections += currentDiscs;
                j++;
            }
        }
        return intersections;
    }
}

- Suketu Vakharia January 20, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
-1
of 3 vote

Sounds like a programming contest question. Is it really google onsite question?

- Anonymous February 22, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
-1
of 1 vote

This solution has some drawbacks as mentioned by others. So, I remove it no to confuse anyone.

- Towhid February 23, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

The worst case complexity is not O(NlogN), it is O(N^2). Consider the case in which A[i]=N for all i.

- Anonymous February 23, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

You forgot the fact that they are circles. The assumption that the circles starting from the points within the range of list[p].r will be the only ones who are intersecting is wrong.
For example lets take a circle starting at (0,10) with radius 6 and another circle at (0,2) with radius 4. Now the point(0,2) does not come under the range of the circle at (0,10) but still if you notice they do intersect.

- Someone February 23, 2013 | Flag
Comment hidden because of low score. Click to expand.
-1
of 1 vote

# include <stdio.h>
# include <conio.h>

int max(int a , int b){
    if (a>=b) return a;
    else return b;
}


int main(){
    int inp[7] = {2,4,0,1,6,5,3};
    int i,j, ctr=0;
    for(i = 0; i<=6; i++)
       for(j = i+1; j<=6; j++)
          if( max(inp[i], inp[j]) >= (j-i)) 
                ctr++;

              
    printf("%d", ctr); 
    getch();
 }

The o/p for above program is 17.

When i change the inp[7] to a sorted array, the o/p is 21. This 21 is basically the sum of all elements of the inp[] array.

2,4,1,0,6,5,3
6,5,4,0,3,2,1
* * * *

The asterisks show the positions where sorted array element is higher than original element.
Number of asterisks is 4.

Subtracting the number of astersiks from 21(sum of the array) gives 17.

I have tested it for few examples and seems to be fine.

So, sorting time complexity is nlogn, storing the sorted array has space complexity of n.

- Anonymous February 23, 2013 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

can you explain?

what do you sort?

- adam2008 February 23, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

The code i posted is bruteforce. That is just for testing my solution.

I mean to say

1. Add the elements of the input array (say input_arr) and store in int variable ctr.
2. Sort the input array and store in another array say sort_arr.
3. Loop through and find "for how many indices, sort_arr[i] >= input_arr[i]"
In my previous comment, ive indicated this by asterisks.
4. Subtract the value of step 3 from int variable ctr.

- Anonymous February 23, 2013 | Flag


Add a Comment
Name:

Writing Code? Surround your code with {{{ and }}} to preserve whitespace.

Books

is a comprehensive book on getting a job at a top tech company, while focuses on dev interviews and does this for PMs.

Learn More

Videos

CareerCup's interview videos give you a real-life look at technical interviews. In these unscripted videos, watch how other candidates handle tough questions and how the interviewer thinks about their performance.

Learn More

Resume Review

Most engineers make critical mistakes on their resumes -- we can fix your resume with our custom resume review service. And, we use fellow engineers as our resume reviewers, so you can be sure that we "get" what you're saying.

Learn More

Mock Interviews

Our Mock Interviews will be conducted "in character" just like a real interview, and can focus on whatever topics you want. All our interviewers have worked for Microsoft, Google or Amazon, you know you'll get a true-to-life experience.

Learn More