-1

I'm trying to figure out the algorithm to implement a method and I would need some advice in the regard. I have given an array and range,

A = [1, 15, 30, 40, 50]
range =  10

I need to figure out the minimum number of points that would cover all the numbers of the given array.

Cover means that distance you can reach both left and right with the provided range. For example, if I have a point at 23 and range of 5, then I can reach 18-23 left side and 23-28 right side. The points can cover both the left and the right sides of the given range.

In the provided array the result is 3. We would need one point at 1, another at 15, and 3rd one at 40. I explain it below,

i. The point at 1 will cover till 10 (1-10)
ii. The point at 15 will cover itself (15)
iii.  The point at 40 will cover left till the 30 and at the right till the 50 (30-40-50)

Please, provide a good reason before you attempt to downvote. Thank you.

Arefe
  • 11,321
  • 18
  • 114
  • 168
  • why was this downvoted? this is an interesting question – Solace Sep 21 '18 at 06:20
  • 2
    I suspect because OP has shown no attempt, so it looks like s/he just wants us to solve a homework problem. – Andy Turner Sep 21 '18 at 06:21
  • What's stopped you from implementation of the simplest algorithm (start new interval if you meet incovered point)? – MBo Sep 21 '18 at 06:25
  • @MBo I think the complexity will be with the left side of the range.. i.e. looking back.. also, you can't just "start new interval" as you might need to remove previously counted interval if the new one covers more elements – Kartik Sep 21 '18 at 06:28
  • 1
    @Yoda There is no need to delete. Question might be interesting for community. Just make it better. – MBo Sep 21 '18 at 06:37
  • 2
    @Yoda that's not true.. it was closed because it was unclear back then, and no attempt was shown. It is not fair for the community to delete it now that you have got your solution. – Kartik Sep 21 '18 at 06:40
  • 1
    @Yoda I believe - when you show own thoughts, some DVs will be removed. – MBo Sep 21 '18 at 06:50
  • @Yoda Can we assume the array is sorted? – dWinder Sep 21 '18 at 08:02
  • Then one can use greedy algorithm with save the max cover area and then add index if not covered – dWinder Sep 21 '18 at 08:12
  • 1
    @Yoda I assume in my answer the point can be choosen even if not exist in the input array. Is that so? Or points can be selected only from the input? – dWinder Sep 21 '18 at 10:00
  • @Yoda edit my answer with constrain of choosing points from the array – dWinder Sep 21 '18 at 13:03

3 Answers3

1

I'll try to make it concise by using the Stream API if I get time:-

public static void main(String[] args) {
    int[] arr = {1, 15, 30, 40, 50};
    int range = 10;
    Map<Integer, Set<Integer>> map = new HashMap<>(arr.length); //maps indexes of elements to the indexes of elements it covers

    for (int i = 0; i < arr.length; i++) {
        for (int j : arr) {
            if (j >= arr[i] - range && j <= arr[i] + range) {
                if (map.get(i) == null) {
                    Set<Integer> set = new HashSet<>();
                    set.add(j);
                    map.put(i, set);
                } else {
                    map.get(i).add(j);
                }
            }
        }
    }
    Set<Integer> mapEntriesToDelete = new HashSet<>();
    for (Map.Entry<Integer, Set<Integer>> e : map.entrySet()) {
        for (Map.Entry<Integer, Set<Integer>> f : map.entrySet()) {
            if (!e.getKey().equals(f.getKey()) && e.getValue().containsAll(f.getValue())) {
                mapEntriesToDelete.add(f.getKey());
            }
        }
    }
    mapEntriesToDelete.forEach(map::remove);
    System.out.println("Points: " + map.size());
    System.out.print("At indexes: ");
    map.keySet().forEach(k -> System.out.print(k + ","));
}

Output

Points: 3
At indexes: 0,1,3,
Kartik
  • 7,677
  • 4
  • 28
  • 50
  • We implemented a solution with better time-complexity that you may like to have a look. – Arefe Sep 21 '18 at 17:48
1

If the array is sorted one can use greedy algorithm. I also assume that all number in the input are positive.

Consider the following steps:

1. Int cover = -1, points= new array
2. For each element in the array:
   2.1 . If element > cover then:
       2.1.1 cover = element + range - 1 // biggest value that still cover the element
       2.1.2 push to point cover value

The points array will contain the mimium points needed to cover the array for given range

Complexity: assuming n is the size of the input array:

Time complexity is O(n) if the array is sorted and O(nlogn) if not. Space complexity is O(k) when k is the number of cover points which bounded by n. If all you want is the number of the points then space complexity is O(1)

If the points can only be chosen from the array you can modify the algorithm as follow:

1. Int cover = -1, points= new array
2. For each i in the array.length:
    2.1 If array[i] > cover then:
        2.1.1 cover = array[i] //element can cover itself 
        2.1.2 for (j=i+1; array[j] < array[i] + range; j++) // find the largest element who still cover array[i]
            2.1.2.1 cover = array[j] // element in index j cover also index i
        2.1.3 push to point cover value
        2.1.4 add range to cover // to mark for cover after a[j]

The space complexity is the same. Time complexity is also O(n) - because every step the inner loop (j) is doing the i-loop we fail the condition of the if statement - so we stay with O(n).

dWinder
  • 11,597
  • 3
  • 24
  • 39
0

I programmed the algorithm proposed by David in the earlier answer. The code is provided below,

public static int getMinNumberOfPoints(int R, int[] A) {

    int cover = -1;
    int N = A.length;

    List<Integer> list = new ArrayList<>();

    int count = 0;

    for (int i = 0; i < N; i++) {

        if (A[i] > cover) {

            cover = A[i];

            /*
             * find the largest element who still cover A[i]
             * */
            for (int j = i + 1; j < N && A[i] + R >= A[j]; j++) {
                cover = A[j];
            }

            /*
            * add the cover to keep track for camera placement
            * */
            list.add(cover);
            count++;

            cover += R;
        }
    }

    return count;
}
Arefe
  • 11,321
  • 18
  • 114
  • 168