Open In App

Queries to find the future closest date

Improve
Improve
Like Article
Like
Save
Share
Report

Given an array arr[] consisting of N strings and an array Query[] consisting of Q queries. Each string in arrays arr[] and Query[] is of the form D/M/Y where D, M and Y denotes the date, month and year. For each query, the task is to print the next closest date from the given array arr[]. If no such date exists, print “-1”.

Examples:

Input: arr[]={“22/4/1233”, “1/3/633”, “23/5/56645”, “4/12/233”}, Q = 2, 
Query[] = {“23/3/4345”, “12/3/2”}
Output:
23/5/56645
4/12/233
Explanation:
Query 1: The closest date after “23/3/4345” is “23/5/56645”.
Query 2: The closest date after “12/3/2” is “4/12/233”.

Input: arr[]={“22/4/1233”, “4/12/233”, “1/3/633”, “23/5/56645”}, Q = 1, 
Query[] = {“4/4/34234234”}
Output: -1

Naive Approach: The simplest approach for each query in the array Query[] is to traverse the array arr[] and for each date, check if it is greater than the current date or not and if it closest to it or not. After complete traversal of the array, print the closest date obtained. If no date is found, print -1.

Time Complexity: O(N*Q)
Auxiliary Space: O(1)

Efficient Approach: The idea is to sort the given array arr[] using a comparator function. Then use a Binary Search to find the future date closest to each date in Query[]. Follow the steps below to solve the problem:

  1. Sort the array of dates arr[] by comparing the year first, then the month followed by the day.
  2. After sorting the array in the above step, for each query, find the closest date using binary search to compare two dates use the comparator function.
  3. If no valid date is found, then print “-1”.
  4. Otherwise, print the closest date found.

Below is the implementation of the above approach: 

C++




// C++ program for the above approach
 
#include <bits/stdc++.h>
 
using namespace std;
 
vector<string> tokenize(string s, string del)
{
    vector<string> res;
    int start, end = -1 * del.size();
    do {
        start = end + del.size();
        end = s.find(del, start);
        res.push_back(s.substr(start, end - start));
    } while (end != -1);
    return res;
}
 
// Comparator function to compare
// the two dates
int comp(string s, string t)
{
 
    // Split the dates strings
    // when a "/" found
    vector<string> ss = tokenize(s, "/");
    vector<string> tt = tokenize(t, "/");
 
    int date1[3];
    int date2[3];
 
    // Store the dates in form
    // of arrays
    for (int i = 0; i < 3; i++) {
        date1[i] = stoi(ss[i]);
        date2[i] = stoi(tt[i]);
    }
 
    // If years are not same
    if (date1[2] != date2[2]) {
        return date1[2] - date2[2];
    }
 
    // If months are not same
    else if (date1[1] != date2[1]) {
        return date1[1] - date2[1];
    }
 
    // If days are not same
    else if (date1[0] != date2[0]) {
        return date1[0] - date2[0];
    }
 
    // If two date is same
    return 0;
}
 
// Function to print the next
// closest date
string nextClosestDate(vector<string> arr, string q)
{
    // Sort date array
    sort(arr.begin(), arr.end(), comp);
 
    // Perform the Binary search
    // to answer the queries
    int l = 0, r = arr.size() - 1;
    int ind = -1;
 
    // Iterate until l <= r
    while (l <= r) {
 
        // Find mid m
        int m = (l + r) / 2;
 
        // Comparator function call
        int c = comp(q, arr[m]);
 
        // If comp function return 0
        // next closest date is found
        if (c == 0) {
            ind = m;
            break;
        }
 
        // If comp function return
        // less than 0, search in
        // the left half
        else if (c < 0) {
            r = m - 1;
            ind = m;
        }
 
        // If comp function return
        // greater than 0, search
        // in the right half
        else {
            l = m + 1;
        }
    }
 
    // Return the result
    if (ind == -1) {
        return "-1";
    }
    else {
        return arr[ind];
    }
}
 
void performQueries(vector<string> arr, vector<string> Q)
{
    // Traverse the queries of date
    for (int i = 0; i < Q.size(); i++) {
 
        // Function Call
        cout << nextClosestDate(arr, Q[i]) << endl;
    }
}
 
// Driver Code
int main()
{
    // Given array of dates
    vector<string> arr = { "22/4/1233", "1/3/633",
                           "23/5/56645", "4/12/233" };
 
    // Given Queries
    vector<string> Q
        = { "23/3/4345", "4/4/34234234", "12/3/2" };
 
    // Function Call
    performQueries(arr, Q);
}
 
// This code is contributed by phasing17.


Java




// Java program for the above approach
import java.awt.*;
import java.io.*;
import java.util.*;
 
class GFG {
 
    // Comparator function to compare
    // the two dates
    public static int comp(String s,
                           String t)
    {
 
        // Split the dates strings
        // when a "/" found
        String[] ss = s.split("/");
        String[] tt = t.split("/");
 
        int date1[] = new int[3];
        int date2[] = new int[3];
 
        // Store the dates in form
        // of arrays
        for (int i = 0; i < 3; i++) {
            date1[i]
                = Integer.parseInt(ss[i]);
            date2[i]
                = Integer.parseInt(tt[i]);
        }
 
        // If years are not same
        if (date1[2] != date2[2]) {
            return date1[2] - date2[2];
        }
 
        // If months are not same
        else if (date1[1] != date2[1]) {
            return date1[1] - date2[1];
        }
 
        // If days are not same
        else if (date1[0] != date2[0]) {
            return date1[0] - date2[0];
        }
 
        // If two date is same
        return 0;
    }
 
    // Function to print the next
    // closest date
    public static String
    nextClosestDate(String arr[],
                    String q)
    {
        // Sort date array
        Arrays.sort(arr,
                    new Comparator<String>() {
 
                        @Override
                        public int compare(String o1,
                                           String o2)
                        {
                            return comp(o1, o2);
                        }
                    });
 
        // Perform the Binary search
        // to answer the queries
        int l = 0, r = arr.length - 1;
        int ind = -1;
 
        // Iterate until l <= r
        while (l <= r) {
 
            // Find mid m
            int m = (l + r) / 2;
 
            // Comparator function call
            int c = comp(q, arr[m]);
 
            // If comp function return 0
            // next closest date is found
            if (c == 0) {
                ind = m;
                break;
            }
 
            // If comp function return
            // less than 0, search in
            // the left half
            else if (c < 0) {
                r = m - 1;
                ind = m;
            }
 
            // If comp function return
            // greater than 0, search
            // in the right half
            else {
                l = m + 1;
            }
        }
 
        // Return the result
        if (ind == -1) {
            return "-1";
        }
        else {
            return arr[ind];
        }
    }
 
    public static void
        performQueries(String[] arr,
                       String[] Q)
    {
        // Traverse the queries of date
        for (int i = 0; i < Q.length; i++) {
 
            // Function Call
            System.out.println(
                nextClosestDate(arr, Q[i]));
        }
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        // Given array of dates
        String arr[] = { "22/4/1233",
                         "1/3/633",
                         "23/5/56645",
                         "4/12/233" };
 
        // Given Queries
        String Q[]
            = { "23/3/4345",
                "4/4/34234234",
                "12/3/2" };
 
        // Function Call
        performQueries(arr, Q);
    }
}


Python3




# Python3 program for the above approach
import functools
 
# Comparator function to compare
# the two dates
def comp(s, t):
 
    # Split the dates strings
    # when a "/" found
    ss = s.split("/");
    tt = t.split("/");
     
    # Store the dates in form
    # of arrays
    date1 = [int(ele) for ele in ss]
    date2 =[int(ele) for ele in tt]
     
 
    # If years are not same
    if (date1[2] != date2[2]):
        return date1[2] - date2[2];
     
 
    # If months are not same
    elif (date1[1] != date2[1]) :
        return date1[1] - date2[1];
     
 
    # If days are not same
    elif (date1[0] != date2[0]) :
        return date1[0] - date2[0];
     
 
    # If two date is same
    return 0;
 
# Function to print the next
# closest date
def nextClosestDate(arr, q):
 
    # Sort date array
    arr.sort(key = functools.cmp_to_key(comp))
 
    # Perform the Binary search
    # to answer the queries
    l = 0
    r = len(arr) - 1
         
    ind = -1;
 
    # Iterate until l <= r
    while (l <= r) :
 
        # Find mid m
        m = int((l + r) / 2);
 
        # Comparator function call
        c = comp(q, arr[m]);
 
        # If comp function return 0
        # next closest date is found
        if (c == 0) :
            ind = m;
            break;
         
 
        # If comp function return
        # less than 0, search in
        # the left half
        elif (c < 0) :
            r = m - 1;
            ind = m;
         
        # If comp function return
        # greater than 0, search
        # in the right half
        else :
            l = m + 1;
         
    # Return the result
    if (ind == -1) :
        return "-1";
     
    else :
        return arr[ind];
     
def performQueries(arr, Q):
 
    # Traverse the queries of date
    for i in range(len(Q)):
 
        # Function Call
        print(nextClosestDate(arr, Q[i]));
     
# Driver Code
 
# Given array of dates
arr =[ "22/4/1233", "1/3/633", "23/5/56645", "4/12/233" ];
 
# Given Queries
Q = [ "23/3/4345", "4/4/34234234", "12/3/2" ];
 
# Function Call
performQueries(arr, Q);
 
# This code is contributed by phasing17.


C#




// C# program for the above approach
using System;
using System.Collections.Generic;
 
class GFG {
 
  // Comparator function to compare
  // the two dates
  public static int comp(string s,
                         string t)
  {
 
    // Split the dates strings
    // when a "/" found
    string[] ss = s.Split("/");
    string[] tt = t.Split("/");
 
    int[] date1 = new int[3];
    int[] date2 = new int[3];
 
    // Store the dates in form
    // of arrays
    for (int i = 0; i < 3; i++) {
      date1[i]
        = Convert.ToInt32(ss[i]);
      date2[i]
        = Convert.ToInt32(tt[i]);
    }
 
    // If years are not same
    if (date1[2] != date2[2]) {
      return date1[2] - date2[2];
    }
 
    // If months are not same
    else if (date1[1] != date2[1]) {
      return date1[1] - date2[1];
    }
 
    // If days are not same
    else if (date1[0] != date2[0]) {
      return date1[0] - date2[0];
    }
 
    // If two date is same
    return 0;
  }
 
  // Function to print the next
  // closest date
  public static string
    nextClosestDate(string[] arr,
                    string q)
  {
    // Sort date array
    Array.Sort(arr, comp);
 
    // Perform the Binary search
    // to answer the queries
    int l = 0, r = arr.Length - 1;
    int ind = -1;
 
    // Iterate until l <= r
    while (l <= r) {
 
      // Find mid m
      int m = (l + r) / 2;
 
      // Comparator function call
      int c = comp(q, arr[m]);
 
      // If comp function return 0
      // next closest date is found
      if (c == 0) {
        ind = m;
        break;
      }
 
      // If comp function return
      // less than 0, search in
      // the left half
      else if (c < 0) {
        r = m - 1;
        ind = m;
      }
 
      // If comp function return
      // greater than 0, search
      // in the right half
      else {
        l = m + 1;
      }
    }
 
    // Return the result
    if (ind == -1) {
      return "-1";
    }
    else {
      return arr[ind];
    }
  }
 
  public static void
    performQueries(string[] arr,
                   string[] Q)
  {
    // Traverse the queries of date
    for (int i = 0; i < Q.Length; i++) {
 
      // Function Call
      Console.WriteLine(
        nextClosestDate(arr, Q[i]));
    }
  }
 
  // Driver Code
  public static void Main(string[] args)
  {
    // Given array of dates
    string[] arr = { "22/4/1233",
                    "1/3/633",
                    "23/5/56645",
                    "4/12/233" };
 
    // Given Queries
    string[] Q
      = { "23/3/4345",
         "4/4/34234234",
         "12/3/2" };
 
    // Function Call
    performQueries(arr, Q);
  }
}
 
// This code is contributed by phasing17.


Javascript




// JavaScript program for the above approach
 
// Comparator function to compare
// the two dates
function comp(s, t)
{
 
    // Split the dates strings
    // when a "/" found
    let ss = s.split("/");
    let tt = t.split("/");
 
    let date1 = new Array(3);
    let date2 = new Array(3);
 
    // Store the dates in form
    // of arrays
    for (var i = 0; i < 3; i++) {
        date1[i] = parseInt(ss[i]);
        date2[i] = parseInt(tt[i]);
    }
 
    // If years are not same
    if (date1[2] != date2[2]) {
        return date1[2] - date2[2];
    }
 
    // If months are not same
    else if (date1[1] != date2[1]) {
        return date1[1] - date2[1];
    }
 
    // If days are not same
    else if (date1[0] != date2[0]) {
        return date1[0] - date2[0];
    }
 
    // If two date is same
    return 0;
}
 
// Function to print the next
// closest date
function nextClosestDate(arr, q)
{
    // Sort date array
 
    arr.sort(function(a, b){ return comp(a, b) })
 
        // Perform the Binary search
        // to answer the queries
        let l
        = 0,
        r = arr.length - 1;
    let ind = -1;
 
    // Iterate until l <= r
    while (l <= r) {
 
        // Find mid m
        let m = Math.floor((l + r) / 2);
 
        // Comparator function call
        let c = comp(q, arr[m]);
 
        // If comp function return 0
        // next closest date is found
        if (c == 0) {
            ind = m;
            break;
        }
 
        // If comp function return
        // less than 0, search in
        // the left half
        else if (c < 0) {
            r = m - 1;
            ind = m;
        }
 
        // If comp function return
        // greater than 0, search
        // in the right half
        else {
            l = m + 1;
        }
    }
 
    // Return the result
    if (ind == -1) {
        return "-1";
    }
    else {
        return arr[ind];
    }
}
 
function performQueries(arr, Q)
{
    // Traverse the queries of date
    for (var i = 0; i < Q.length; i++) {
 
        // Function Call
        console.log(nextClosestDate(arr, Q[i]));
    }
}
 
// Driver Code
 
// Given array of dates
let arr =
    [ "22/4/1233", "1/3/633", "23/5/56645", "4/12/233" ];
 
// Given Queries
let Q = [ "23/3/4345", "4/4/34234234", "12/3/2" ];
 
// Function Call
performQueries(arr, Q);
 
// This code is contributed by phasing17.


Output: 

23/5/56645
-1
4/12/233

 

Time Complexity: O((N*log N) + (Q*log N)) 
Auxiliary Space: O(1)



Last Updated : 14 Dec, 2022
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads