×

Minimum Number of Taps to Open to Water a Garden in Java

Problem Statement

The issue is that a gardener wants to water a (single-dimensional) garden using the fewest possible tap openings. The goal is to determine the minimum necessary taps to be open to water the entire garden adequately. If this is not possible, return -1.

The solution to the Problem

For the sake of simplicity, it is assumed that the garden is one-dimensional along an axis of length L, starting at point 0 and ending at point L. The points posArr = [0, 1, 2,..., T] in the garden are where T + 1 taps are located. For the jth tap, the range is defined as (j - rangeArr[j], j + rangeArr[j]). The range of a tap is specified in the array rangeArr[]. Keep in mind that if the entire garden cannot be watered, the console must display the proper message. 

To help you understand, let's look at an example of it.

Example

Input

 L = 5, rangeArr = [3,4,1,1,0,0]

Output

 1

Explanation

The tap at point 0 can cover the interval [-3,3]

The tap at point 1 can cover the interval [-3,5]

The tap at point 2 can cover the interval [1,3]

The tap at point 3 can cover the interval [2,4]

The tap at point 4 can cover the interval [4,4]

The tap at point 5 can cover the interval [5,5]

Opening Only the second tap will water the whole garden [0,5]

Example with diagram

Input

L = 5, rangeArr = [1, 2, 3, 0, 4, 2]

Output

1

Explanation

  • rangeArr[0] is 1 for the first location tap. The range is therefore [0 - 1, 0 + 1] = [-1, 1].
  • rangeArr[1] is 2 for the second location tap. The range is therefore [1 - 2, 1 + 2] = [-1, 3].
  • rangeArr[2] is 3 for the third location tap. It follows that the range is [2 - 3, 2 + 3] = [-1, 5].
  • rangeArr[3] is 0 for the fourth location tap. The range is thus [3 - 0, 3 + 0] = [3, 3].
  • rangeArr[4] is equal to 4 for the fifth location tap. It follows that the range is [4 - 4, 4 + 4] = [0, 8].
  • rangeArr[5] is 2 for the sixth location tap. The available range is [5 - 2, 5 + 2] = [3, 7].

The same is depicted in the diagram below.

Minimum Number of Taps to Open to Water a Garden in Java

According to the diagram above, we can either open a tap in the third position rangeArr[2] or a tap in the fifth position range Arr[4]. This is because these taps can cover the entire length of the garden, ranging from 0 to 5. As a result, the answer is 1.

Algorithm

Step 1: To solve the problem, convert the array rangeArr[] into a list of intervals and sort them. Sorting should be done based on the starting point of the specified taps' range. Maintain the interval sorting in the array intervals[].

Step 2: Select an element from the array intervals[] (Picking should be done from left to right) and check the range's beginning and ending points (use the loop for picking the elements from the interval). There must be another tap within the range's finishing point; if it is not present, it is impossible to water the entire garden, so we can stop here to display an appropriate message. If the range is present, select the tap whose range is present and increment the tap count.

Step 3: Repeat step 2 for each tap until we locate a tap that can span the entire garden on its own or we have traversed all of the array intervals[]. Return the number of taps that are necessary (count of the tap).

The algorithm mentioned above is implemented as follows.

Filename: FillGardenWithWater.java

// significant import statements
import java.util.Comparator ;  
import java.util.Arrays ;  
public class FillGardenWithWater   
{      
    public int minTapsFill(int rangeArr[], int size)   
    {         
        // Initializing the answer  
        int tapCount = 0 ;  
          
        int arrSize = rangeArr.length ;  
  
        // intervalFlow array that will include each tap's range
        int intervalFlow[][] = new int[arrSize][2] ;  
        // The for loop is used to store the range.
        for(int j = 0; j < arrSize; j++)   
        {  
            // identifying the starting and stopping places of the jth tap   
            int st ;  
            int ed ;  
  
            // Since the garden begins at 0         
            if(j - rangeArr[j] >= 0)   
            {  
                st = j - rangeArr[j] ;  
            }  
            else   
            {  
                st = 0 ;  
            }  
  
            ed = j + rangeArr[j] ;  
  
            //range is being added to the array intervalFlow
            intervalFlow[j][0] = st ;  
            intervalFlow[j][1] = ed ;  
              
        }  
  
        // utilising the starting point to sort the intervalFlow. 
        // The tap with the earliest starting point will be selected first.
        Arrays.sort(intervalFlow, new Comparator<int[]>()   
        {   
            @Override                
            //Compare values based on columns
            public int compare(int[] e1, int[] e2)   
            {   
     
                if (e1[0] == e2[0])   
                {   
                    return e1[1] - e2[1] ;   
                }  
                return e1[0] - e2[0] ;   
  
            }   
        }) ;  
  
        //the range that has been covered by the 
        //taps that have been walked through
        int maximumRange = 0 ;  
          
        // the current tap's range
        // that one is traversing right now  
        int nextMaximumRange = 0 ;  
          
        // for traversing the array's elements
        // array intervalFlow[][]  
        int j = 0 ;  
  
        // Traversing the intervals  
        while(j < intervalFlow.length)   
        {  
  
            // the range goes out of the garden  
            if(maximumRange >= size)   
            {  
                return tapCount ;  
            }  
  
               
            // If in the range of the garden
            //By opening the existing tap, you can extend the range.
            if(intervalFlow[j][0] <= maximumRange)   
            {  
  
                while(j < intervalFlow.length && intervalFlow[j][0] <= maximumRange)   
                {  
                    nextMaximumRange = Math.max(nextMaximumRange, intervalFlow[j][1]) ;  
                    j = j + 1 ;  
                }  
            }  
            // dealing with the Case
            else   
            {  
                return -1 ;  
            }  
            // Updating the maximum water flow
            maximumRange = nextMaximumRange ;  
  
            // Activating the current tap
            tapCount = tapCount + 1 ;  
              
        }  
        return tapCount ;  
    }  
      
    // main method  
    public static void main(String argvs[])  
    {  
        // making an object of the FillGardenWithWater class 
        FillGardenWithWater obj = new FillGardenWithWater() ;  
          
        // range of the garden is from 0 to 5  
        int L = 5 ;  
          
        // range of taps   
  
        // input 1  
        int rangeArr[] = {1, 2, 3, 0, 4, 2} ;  
        int answer = obj.minTapsFill(rangeArr, L) ;  
          
        if(answer == -1)  
        {  
            System.out.println("The taps cannot water the whole park.") ;  
        }  
        else  
        {  
            System.out.println("The minimum number of taps required to water the whole park is: " + answer) ;  
        }  
          
  
         // input 2  
        int rangeArr1[] = {3, 1, 1, 1, 0, 0} ;  
        answer = obj.minTapsFill(rangeArr1, L) ;  
          
        if(answer == -1)  
        {  
            System.out.println("The taps cannot water the whole park.") ;  
        }  
        else  
        {  
            System.out.println("The minimum number of taps required to water the whole park is: " + answer) ;  
        }  
          
        // input 3  
        int rangeArr2[] = {1, 1, 1, 1, 1, 1} ;  
        answer = obj.minTapsFill(rangeArr2, L) ;  
          
        if(answer == -1)  
        {  
            System.out.println("The taps cannot water the whole park.") ;  
        }  
        else  
        {  
            System.out.println("The minimum number of taps required to water the whole park is: " + answer) ;   
        }  
          
    }  
  
}  

Output

Minimum Number of Taps to Open to Water a Garden in Java

Complexity Analysis

We utilized loops and sorting in the preceding code. The loop yields O(n) in time, and the sorting is O(n * log(n)) in time. As a result, the program's total time complexity is O(n + n * log(n)), where n is the total number of taps located. Because the range is also stored in an array, the space complexity of the preceding program is O(n).

We can improve the preceding strategy by avoiding sorting. The following method illustrates this.

Optimized Method

Step 1: In this method, construct a jumpArr[] of size L + 1 to keep track of the maximum range that may be reached from the specified index (current index). To accomplish this, assign the value -1 to each entry of the array jumpArr[]. A value of -1 for any index indicates that it is impossible to attain that value (coordinate).

Step 2: Create a variable called tapCount and set it to 1.

Step 3: Find the range for each tap by iterating through the array rangesArr[]. The range can be calculated as:

start = maximum from (0, i - rangesArr[i])

end = minimum from (L, i + rangesArr[i])

Step 4: Update the jumpArr[] array as jumpArr[start] = maximum from  (jumpArr[start], end). It is not possible to water the entire garden if jumpArr[0] = -1.

Step 5: Give the value jumpArr[0] to a variable called current. Take nxt and j as two additional variables as well. Both of them should be assigned the number 0.

While current <  L, it indicates that the garden will receive a full watering at the last index L.

While j < current,  
update nxt = maximum from (nxt and jumpArr[j])  
increment j by 1.  

It is impossible to move ahead if the nxt is the same as the current. As a result, it is only possible to water some of the ground.

current should be updated using nxt if it differs from current, and the tapCount should be updated by adding 1 to it.

Let's use a Java program to implement the above technique.

FileName: FillGardenWithWater1.java

// significant import statement  
import java.util.Arrays ;  
public class FillGardenWithWater1   
{      
    public int minTapsFill(int rangeArr[], int L)   
    {         
        // Initializing the answer  
        int tapCount = 1 ;  
        int arrSize = rangeArr.length ;  
        // Initializing the array of the size L + 1 with all the values as -1  
        int jumpArr[] = new int[L + 1];  
        Arrays.fill(jumpArr, -1) ;  
        // Traversing the array rangeArr[]  
        for(int j = 0; j <= L; j++)   
        {  
                //Updating the jumpArr[] array with
                //the maximum flow possible
            // calculating the range for each tap
            // The start of the range is at st
             //As the value that goes beyond
            //The number 0 serves no use. As a result, 
            //we check with a value of 0.  
            int st = Math.max(0, j - rangeArr[j]) ;  
             // The range's termination point is ed.
             //As the value that goes beyond   
            // L has no practical use. As a result, 
            //we verify using the value L.  
            int ed = Math.min(L, j + rangeArr[j]) ;  
            jumpArr[st] = Math.max(jumpArr[st], ed) ;  
        }  
        // Indicating that no tap is able to water the  
        // first coordinate of the garden  
        if(jumpArr[0] == -1)   
        {  
            return -1 ;  
        }  
              //current suggests that in order to achieve 
              //the maximum flow, the tap must be opened.
        int current = jumpArr[0] ;  
        int j = 0 ;  
        int nxt = 0 ;  
  
        // for traversing the garden completely  
        while (current < L)   
        {  
              //Finding the next tap to open in order to water 
              //the largest possible area of the garden,
              //it is done to limit the number of taps
              //to a minimum(count of taps to a minimum).
            while (j <= current)   
            {  
                nxt = Math.max(nxt, jumpArr[j]) ;  
                j = j + 1 ;  
            }  
           //it denotes that advancement is not feasible.
          //Consequently, it is impossible
          //to water the entire garden.
            if (nxt == current)   
            {  
                return -1 ;  
            }  
            // Using the current tap   
            current = nxt ;  
            // updating the answer  
            tapCount = tapCount + 1 ;         
        }  
        return tapCount ;  
    }      
    // main method  
    public static void main(String argvs[])  
    {  
        FillGardenWithWater1 obj = new FillGardenWithWater1() ;  
        // range of the garden is from 0 to 5  
        int L = 5 ;          
        // range of taps   
        // input 1  
        int rangeArr[] = {1, 2, 3, 0, 4, 2} ;  
        int answer = obj.minTapsFill(rangeArr, L) ;          
        if(answer == -1)  
        {  
            System.out.println("The taps cannot water the whole park.") ;  
        }  
        else  
        {  
            System.out.println("The minimum number of taps required to water the whole park is: " + answer) ;  
        }  
         // input 2  
        int rangeArr1[] = {3, 1, 1, 1, 0, 0} ;  
        answer = obj.minTapsFill(rangeArr1, L) ;  
        if(answer == -1)  
        {  
            System.out.println("The taps cannot water the whole park.") ;  
        }  
        else  
        {  
            System.out.println("The minimum number of taps required to water the whole park is: " + answer) ;  
        }  
        // input 3  
        int rangeArr2[] = {1, 1, 1, 1, 1, 1} ;  
        answer = obj.minTapsFill(rangeArr2, L) ;  
        if(answer == -1)  
        {  
            System.out.println("The taps cannot water the whole park.") ;  
        }  
        else  
        {  
            System.out.println("The minimum number of taps required to water the whole park is: " + answer) ;  
        }  
          
    }  
}

Output

Minimum Number of Taps to Open to Water a Garden in Java

Complexity Analysis

We employed the while loop's nesting feature in the program mentioned above. The elements of the array jumpArr[] are still only iterated through once, though. It results from both while loops working in the same direction, which causes the program's time complexity to be O (N). Additionally, we added an auxiliary array to keep track of the maximum range, making the program's space complexity O(N), where N is the total number of taps in the garden.


Related Topics

Access Modifier in Java

The access modifiers in java are used to change the accessibility and scope of a method, constructor, class, and fields. If you are aware of C++ language, when we declare any member...

2 minutes read.

Java import packages

To know about the importing the packages of Java, we need to understand about how to packages work. Packages The package in Java is a collection of Classes and Interfaces. The packages...

3 minutes read.

Java Font

The font is a Java class that is a part of java.awt package. The Serializable interface is implemented by it. The direct recognized child of a Java Font class is...

8 minutes read.

How to generate random numbers in Java

Random numbers, also known as fake numbers, are actually a part of a very large sequence, so they are called random numbers. In a defined set of numbers, every number...

6 minutes read.

Loose Coupling in Java

Loosely coupling mechanism in java means one reference of a variable capable of holding multiple implementation class memory is called loosely coupling. Or in other words, one interface reference variable...

3 minutes read.

Various Operation on Queue using Linked List in Java

We keep track of front and rear pointers in a queue data structure. The head of the line points to the first item, and the back to the last. Rear is...

3 minutes read.

Race Condition in Java

Java is a multi-threaded programming language, race conditions are more likely to arise. Mostly because data can change when multiple threads visit the same resource simultaneously. Race conditions are concurrency...

3 minutes read.

Java Static Keyword

It can be either said that static declares the value to be the same, not only in the instance of a class but also as the whole. To declare a variable...

6 minutes read.

Creating a Custom Generic Class in Java

To indicate parameter types when creating generic classes, we utilize the <> symbol. The syntax used to generate objects of a generic class is as follows. // To create an instance...

4 minutes read.

Equilibrium Index of an Array in Java

An array's equilibrium index is the condition where the sum of items with lower and higher indices equals. For example, an array A=[-4,5 2,6,-5] where: a[0]=-4, a[1]=5, a[2]=2, a[3]=6, a[4]=-5 Now according...

4 minutes read.

Java Snippets

The term "snippet" refers to a section of code that addresses numerous issues with just a few lines of code. Decreases the number of lines of code and improves programmer...

3 minutes read.

Types of Logical Operators in Java

In this tutorial, we are going to study logical operators. A logical operator is an operator that accomplishes a logical operation that is to connect two or more operations. These...

5 minutes read.

Applet Life Cycle in Java

In this article, we are going to acknowledge you about what a applet is, what is its life cycle and stages in life cycle, along with the syntax and example...

4 minutes read.

Java Command not found

Java Command not found error is displayed if Java is not installed on the computer or if the command prompt cannot find Java.exe to run the program. Our Java software...

3 minutes read.

How to Convert String to Object in Java

How to Convert String to Object in Java The Object is the super class of all classes. So you can assign a string to Object directly. There are two methods to...

3 minutes read.

How to find the length of an Array in Java

Arrays: An array is a sort of container object that stores constant quantities of values of a single type in one memory area. A finite number of items must all be...

3 minutes read.

Java LDAP Authentication

WHAT IS LDAP? Clients can communicate with directory services by sending requests and receiving responses using the Lightweight Directory Access Protocol (LDAP). The term "LDAP server" refers to a directory service...

7 minutes read.

Java Heap Space Out of Memory Error

This error is called an "out of memory" error, which indicates that the JVM cannot allocate an object in memory from the heap. Hence the java.lang.out of memory error, describing...

2 minutes read.

Java Custom Exception

Java Custom Exception Java language facilitates us to create our own exceptions. The class intended to throw the Custom Exception has to be derived from the Java Exceptionor RuntimeExceptionclass. The Java...

4 minutes read.

Upcasting and Downcasting in Java

Type casting in Java is an important and very interesting topic to deal with. But here upcasting and downcasting is somewhat related to typecasting. In normal typecasting, we convert from...

6 minutes read.