Given two arrays S[] and E[] of size N denoting starting and closing time of the shops and an integer value K denoting the number of people, the task is to find out the maximum number of shops they can visit in total if they visit each shop optimally based on the following conditions:
- A shop can be visited by only one person
- A person cannot visit another shop if its timing collide with it
Examples:
Input: S[] = {1, 8, 3, 2, 6}, E[] = {5, 10, 6, 5, 9}, K = 2
Output: 4
Explanation: One possible solution can be that first person visits the 1st and 5th shops meanwhile second person will visit 4th and 2nd shops.Input: S[] = {1, 2, 3}, E[] = {3, 4, 5}, K = 2
Output: 3
Explanation: One possible solution can be that first person visits the 1st and 3rd shops meanwhile second person will visit 2nd shop.Â
Approach: This problem can be solved using the greedy technique called activity selection and sorting. In the activity selection problem, only one person performs the activity but here K persons are available for one activity. To manage the availability of one person a multiset is used.
Follow the steps below to solve the problem:
- Initialize an array a[] of pairs and store the pair {S[i], E[i]} for each index i.
- Sort the array a[] according to the ending time.
- Initialize a multiset st to store the persons with ending time of shop they are currently visiting.
- Initialize a variable ans with 0 to store the final result.
- Traverse each pair of array a[],
- If a person is available i.e a[i].first is greater than or equal to the ending time of any person in the multiset st, then increment the count by 1 and update the ending time of that element with new a[i].second.
- Otherwise, continue checking the next pairs.
- Finally, print the result as count.
Below is the implementation of the above approach:
C++
// C++ program for the above approach Â
#include <bits/stdc++.h> using namespace std; Â
// Comparator bool compareBy( const pair< int , int >& a,                const pair< int , int >& b) {     if (a.second != b.second)         return a.second < b.second;     return a.first < b.first; } // Function to find maximum shops // that can be visited by K persons int maximumShops( int * opening, int * closing,                  int n, int k) {     // Store opening and closing     // time of shops     pair< int , int > a[n]; Â
    for ( int i = 0; i < n; i++) {         a[i].first = opening[i];         a[i].second = closing[i];     } Â
    // Sort the pair of array     sort(a, a + n, compareBy); Â
    // Stores the result     int count = 0; Â
    // Stores current number of persons visiting     // some shop with their ending time     multiset< int > st; Â
    for ( int i = 0; i < n; i++) { Â
        // Check if current shop can be         // assigned to a person who's         // already visiting any other shop         bool flag = false ; Â
        if (!st.empty()) { Â
            auto it = st.upper_bound(a[i].first); Â
            if (it != st.begin()) {                 it--; Â
                // Checks if there is any person whose                 // closing time <= current shop opening                 // time                 if (*it <= a[i].first) { Â
                    // Erase previous shop visited by the                     // person satisfying the condition                     st.erase(it); Â
                    // Insert new closing time of current                     // shop for the person satisfying ?he                     // condition                     st.insert(a[i].second); Â
                    // Increment the count by one                     count++; Â
                    flag = true ;                 }             }         } Â
        // In case if no person have closing         // time <= current shop opening time         // but there are some persons left         if (st.size() < k && flag == false ) {             st.insert(a[i].second);             count++;         }     } Â
    // Finally print the ans     return count; } Â
// Driver Code int main() { Â
    // Given starting and ending time     int S[] = { 1, 8, 3, 2, 6 };     int E[] = { 5, 10, 6, 5, 9 }; Â
    // Given K and N     int K = 2, N = sizeof (S)                    / sizeof (S[0]); Â
    // Function call     cout << maximumShops(S, E, N, K) << endl; } |
Java
import java.util.Arrays; import java.util.Comparator; import java.util.TreeSet; Â
class Main {   public static int maximumShops( int [] opening, int [] closing, int n, int k)   {          // Store opening and closing time of shops     Pair[] a = new Pair[n];     for ( int i = 0 ; i < n; i++) {       a[i] = new Pair(opening[i], closing[i]);     } Â
    // Sort the pair of array     Arrays.sort(a, new Comparator<Pair>() {       @Override       public int compare(Pair a, Pair b) {         if (a.second != b.second) {           return a.second - b.second;         }         return a.first - b.first;       }     }); Â
    // Stores the result     int count = 0 ; Â
    // Stores current number of persons visiting     // some shop with their ending time     TreeSet<Integer> st = new TreeSet<>(); Â
    for ( int i = 0 ; i < n; i++)     {              // Check if current shop can be assigned to       // a person who's already visiting any other shop       boolean flag = false ; Â
      if (!st.isEmpty()) {         Integer it = st.higher(a[i].first);         if (it != null && it <= a[i].first)         {                      // Erase previous shop visited by           // the person satisfying the condition           st.remove(it);                      // Insert new closing time of current shop           // for the person satisfying ?he condition           st.add(a[i].second);                      // Increment the count by one           count++;           flag = true ;         }       } Â
      // In case if no person have       // closing time <= current shop opening time       // but there are some persons left       if (st.size() < k && flag == false ) {         st.add(a[i].second);         count++;       }     } Â
    // Finally return the ans     return count+ 1 ;   } Â
  public static void main(String[] args)   {          // Given starting and ending time     int S[] = { 1 , 8 , 3 , 2 , 6 };     int E[] = { 5 , 10 , 6 , 5 , 9 }; Â
    // Given K and N     int K = 2 , N = S.length; Â
    // Function call     System.out.println(maximumShops(S, E, N, K));   }   static class Pair {     public int first;     public int second; Â
    public Pair( int first, int second) {       this .first = first;       this .second = second;     }   } Â
} Â
// This code is contributed by aadityaburujwale. |
Python3
# Python3 program for the above approach from bisect import bisect_left Â
# Function to find maximum shops # that can be visited by K persons def maximumShops(opening, closing, n, k): Â
    # Store opening and closing     # time of shops     a = [[ 0 , 0 ] for i in range (n)] Â
    for i in range (n):         a[i][ 0 ] = opening[i]         a[i][ 1 ] = closing[i] Â
    # Sort the pair of array     a = sorted (a,key = lambda x: x[ 1 ])          # Stores the result     count = 1 Â
    # Stores current number of persons visiting     # some shop with their ending time     st = {}     for i in range (n): Â
        # Check if current shop can be         # assigned to a person who's         # already visiting any other shop         flag = False Â
        if ( len (st) = = 0 ):             ar = list (st.keys()) Â
            it = bisect_left(ar, a[i][ 0 ]) Â
            if (it ! = 0 ):                 it - = 1 Â
                # Checks if there is any person whose                 # closing time <= current shop opening                 # time                 if (ar[it] < = a[i][ 0 ]): Â
                    # Erase previous shop visited by the                     # person satisfying the condition                     del st[it] Â
                    # Insert new closing time of current                     # shop for the person satisfying ?he                     # condition                     st[a[i][ 1 ]] = 1 Â
                    # Increment the count by one                     count + = 1                     flag = True Â
        # In case if no person have closing         # time <= current shop opening time         # but there are some persons left         if ( len (st) < k and flag = = False ):             st[a[i][ 1 ]] = 1             count + = 1 Â
    # Finally print the ans     return count Â
# Driver Code if __name__ = = '__main__' : Â
    # Given starting and ending time     S = [ 1 , 8 , 3 , 2 , 6 ]     E = [ 5 , 10 , 6 , 5 , 9 ] Â
    # Given K and N     K,N = 2 , len (S) Â
    # Function call     print (maximumShops(S, E, N, K)) Â
    # This code is contributed by mohit kumar 29 |
C#
using System; using System.Linq; using System.Collections.Generic; Â
public class GFG { Â Â Â Â public static int maximumShops( int [] opening, int [] closing, int n, int k) { Â
        // Store opening and closing time of shops         Pair[] a = new Pair[n];         for ( int i = 0; i < n; i++) {             a[i] = new Pair(opening[i], closing[i]);         } Â
        // Sort the pair of array         Array.Sort(a, new Comparison<Pair>((x, y) => {             if (x.second != y.second) {                 return x.second - y.second;             }             return x.first - y.first;         })); Â
        // Stores the result         int count = 0; Â
        // Stores current number of persons visiting         // some shop with their ending time         SortedSet< int > st = new SortedSet< int >(); Â
        for ( int i = 0; i < n; i++) { Â
            // Check if current shop can be assigned to             // a person who's already visiting any other shop             bool flag = false ; Â
            if (st.Any()) {                 int it = st.Where(x => x > a[i].first).FirstOrDefault();                 if (it <= a[i].first) { Â
                    // Erase previous shop visited by                     // the person satisfying the condition                     st.Remove(it); Â
                    // Insert new closing time of current shop                     // for the person satisfying the condition                     st.Add(a[i].second); Â
                    // Increment the count by one                     count++;                     flag = true ;                 }             } Â
            // In case if no person have             // closing time <= current shop opening time             // but there are some persons left             if (st.Count < k && flag == false ) {                 st.Add(a[i].second);                 count++;             }         } Â
        // Finally return the ans         return count;     } Â
    public static void Main( string [] args) { Â
        // Given starting and ending time         int [] S = { 1, 8, 3, 2, 6 };         int [] E = { 5, 10, 6, 5, 9 }; Â
        // Given K and N         int K = 2, N = S.Length; Â
        // Function calla         Console.WriteLine(maximumShops(S, E, N, K));     } Â
    public class Pair {         public int first;         public int second; Â
        public Pair( int first, int second) {             this .first = first;             this .second = second;         }     } } |
Javascript
// Function to find maximum shops // that can be visited by K persons function maximumShops(opening, closing, n, k) { Â
  // Store opening and closing   // time of shops   const a = new Array(n);   for (let i = 0; i < n; i++) {     a[i] = [opening[i], closing[i]];   } Â
  // Sort the pair of array   a.sort((x, y) => x[0] - y[0]); Â
  // Stores the result   let count = 1; Â
  // Stores current number of persons visiting   // some shop with their ending time   const st = {};   for (let i = 0; i < n; i++) { Â
    // Check if current shop can be     // assigned to a person who's     // already visiting any other shop     let flag = false ; Â
    if (Object.keys(st).length === 0) {       const ar = Object.keys(st); Â
      let it = bisect_left(ar, a[i][0]); Â
      if (it !== 0) {         it -= 1; Â
        // Checks if there is any person whose         // closing time <= current shop opening         // time         if (ar[it] <= a[i][0]) { Â
          // Erase previous shop visited by the           // person satisfying the condition           delete st[it]; Â
          // Insert new closing time of current           // shop for the person satisfying ?he           // condition           st[a[i][1]] = 1; Â
          // Increment the count by one           count += 1;           flag = true ;         }       }     } Â
    // In case if no person have closing     // time <= current shop opening time     // but there are some persons left     if (Object.keys(st).length < k && flag === false ) {       st[a[i][1]] = 1;       count += 1;     }   } Â
  // Finally return the result   return count; } Â
// Driver Code (() => {   // Given starting and ending time   const S = [1, 8, 3, 2, 6];   const E = [5, 10, 6, 5, 9]; Â
  // Given K and N   const K = 2, N = S.length; Â
  // Function call   console.log(maximumShops(S, E, N, K)); })(); Â
function bisect_left(arr, x) {Â Â Â let lo = 0; Â Â let hi = arr.length; Â
  while (lo < hi) {     const mid = (lo + hi) >>> 1;     if (arr[mid] < x) {       lo = mid + 1;     } else {       hi = mid;     }   } Â
  return lo; } Â
// This code is contributed by sdeadityasharma |
4
Time complexity: O(NlogN)
Auxiliary Space: O(N)
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!