Given N number of integers in sorted format, where each integer Ai for all(1 ? i ? N), denotes the join of two points (0, Ai) and (Ai, 0) and forms a line by joining these two points, also given Q number of coordinates in form of (X, Y) in the first Quadrant. Return the minimum number of lines needed to cross to reach the origin from (X, Y) in each query. if (X, Y) lies on any of the lines, return -1 as output.
Examples:
Input: N = 2, Points[] = {1, 2}, Q = 1, X = 3, Y = 2
Output: 2
Explanation:There is only one query, In which the point is (2, 3), It can be verified that for reaching origin given point need to cross 2 lines.
Input: N = 3, Points[] = {1, 2, 5}, Q = 3
X = 0, Y = 0
X = 1, Y = 1
X = 4, Y = 3
Output:
0
-1
3
Explanation:
- Query 1:
- (X, Y) are (0, 0), Point is already present at origin, Therefore, no need to cross any line, Output is 0.
- Query 2:
- Given point is (1, 1), Which is present at line joining points (0, 2) and (2, 0). Hence the output is -1, because point is on line.
- Query 3:
- Given point is (3, 4), It can be verified that for reaching origin, We need to cross 3 lines.Hence the output is 3.
Approach: Implement the idea below to solve the problem
The problem is observation based and can be solved by using TreeSet and HashMap. For more clarification of problem see the Concept of approach section below. Using data structure like TreeSet and Map reduces complexity very much.
Concept of approach:
The problem is observation based. There are some points, Which are needed to follow to solve the problem:
- Condition when point lies on any line:
- It should be noted that only those co-ordinates (X, Y) will lie on a line, Whom sum of X and Y co-ordinate is equal to starting of ending point of line. For checking this condition, We will check if HashMap contains (X+Y) or not. If contains then print -1 as output.
- When point doesn’t lie on any line:
- In such condition, Get a floor value of (X+Y) from TreeSet, Formally set.floor(X, Y) and store it in a variable let say floor, If floor is null then print zero else get index of floor, Formally map.get(Floor) from HashMap and store it in the variable let say Index.and print (index+1) as output.
Steps were taken to solve the problem:
- Create TreeSet<Integer> and HashMap<long, Integer> to store values present in Points[].
- Initialize TreeSet with elements of Points[] and HashMap with elements of points along with their index.
- Run a loop for 1 to Q times and follow the below-mentioned steps under the scope of the loop:
- Create a Sum variable and initialize it with (X+Y).
- If HashMap contains Sum, then print -1 as output.
- else get set.floor(Sum) from TreeSet, Then get its index from the map and print it as output.
- Create a Sum variable and initialize it with (X+Y).
Below is the implementation of the above approach:
// C++ code to implement the approach #include <bits/stdc++.h> using namespace std;
// Function to find lines crossed by the point void minimumLines( int N, int points[], int Q,
int X_coordinate[], int Y_coordinate[])
{ // TreeSet for storing points
set< int > set;
// HashMap for storing points and their index
unordered_map< int , int > hash;
// Loop for initializing TreeSet and HashMap
for ( int i = 0; i < N; i++) {
int val = points[i];
set.insert(val);
hash[val] = i;
}
// Loop for number of times Query asked
for ( int i = 0; i < Q; i++) {
// X coordinate
int x = X_coordinate[i];
// Y coordinate
int y = Y_coordinate[i];
// Sum of both coordinates
long sum = x + y;
// Variable to store minimum number of
// lines
int ans = 0;
// Checking if sum exists in HashMap or not
if (hash[sum]) {
// Printing -1 as output.
ans = -1;
cout << (ans) << endl;
continue ;
}
// Checking floor value of sum
auto floor = --set.upper_bound(sum);
// Printing number of lines needed
// to cross by getting floor value
// of sum
if ( floor != set.end()) {
int ind = hash[* floor ];
ans = ind + 1;
}
cout << ans << endl;
}
} // Driver Code int main()
{ int N = 3;
int points[] = { 1, 2, 5 };
int Q = 3;
// X and Y coordinates of Q queries
// formally Q number of (X, Y) points
int X_coordinate[] = { 0, 1, 3 };
int Y_coordinate[] = { 0, 1, 4 };
// Function call
minimumLines(N, points, Q, X_coordinate, Y_coordinate);
} // This code is contributed by Pushpesh Raj. |
// Java code to implement the approach import java.io.*;
import java.lang.*;
import java.util.*;
public class GFG {
// Driver Code
public static void main(String[] args)
throws java.lang.Exception
{
int N = 3 ;
int [] points = { 1 , 2 , 5 };
int Q = 3 ;
// X and Y coordinates of Q queries
// formally Q number of (X, Y) points
int [] X_coordinate = { 0 , 1 , 3 };
int [] Y_coordinate = { 0 , 1 , 4 };
// Function call
minimumLines(N, points, Q, X_coordinate,
Y_coordinate);
}
// Function to find lines crossed by the point
public static void minimumLines( int N, int points[],
int Q,
int X_coordinate[],
int Y_coordinate[])
{
// TreeSet for storing points
TreeSet<Long> set = new TreeSet<>();
// HashMap for storing points and their index
Map<Long, Integer> hash = new HashMap<>();
// Loop for initializing TreeSet and HashMap
for ( int i = 0 ; i < N; i++) {
long val = points[i];
set.add(val);
hash.put(val, i);
}
// Loop for number of times Query asked
for ( int i = 0 ; i < Q; i++) {
// X coordinate
int x = X_coordinate[i];
// Y coordinate
int y = Y_coordinate[i];
// Sum of both coordinates
long sum = x + y;
// Variable to store minimum number of
// lines
int ans = 0 ;
// Checking if sum exists in HashMap or not
if (hash.containsKey(sum)) {
// Printing -1 as output.
ans = - 1 ;
System.out.println(ans);
continue ;
}
// Checking floor value of sum
Long floor = set.floor(sum);
// Printing number of lines needed
// to cross by getting floor value
// of sum
if (floor != null ) {
int ind = hash.get(floor);
ans = ind + 1 ;
}
System.out.println(ans);
}
}
} |
# Python code to implement the approach import bisect
# Driver Code def main():
N = 3
points = [ 1 , 2 , 5 ]
Q = 3
# X and Y coordinates of Q queries
# formally Q number of (X, Y) points
X_coordinate = [ 0 , 1 , 3 ]
Y_coordinate = [ 0 , 1 , 4 ]
# Function call
minimumLines(N, points, Q, X_coordinate,
Y_coordinate)
# Function to find lines crossed by the point def minimumLines(N, points, Q, X_coordinate, Y_coordinate):
# Set for storing points
Set = set ()
# Dictionary for storing points and their index
hash = {}
# Loop for initializing Set and Dictionary
for i in range (N):
val = points[i]
Set .add(val)
hash [val] = i
# Loop for number of times Query asked
for i in range (Q):
# X coordinate
x = X_coordinate[i]
# Y coordinat
y = Y_coordinate[i]
# Sum of both coordinates
Sum = x + y
# Variable to store minimum number of
# lines
ans = 0
# Checking if Sum exists in HashMap or not
if ( Sum in hash ):
# Printing -1 as output.
ans = - 1
print (ans)
continue
# Checking floor value of Sum
floor, val = lowerBound( Set , Sum )
# Printing number of lines needed
# to cross by getting floor value
# of Sum
if (floor > = 0 ):
ind = hash .get(val)
ans = ind + 1
print (ans)
def lowerBound( Set , Sum ):
lb = - 1
Set = list ( Set )
Set .sort()
for val in Set :
if val < Sum :
lb + = 1
else :
break
return lb, Set [lb] if lb > = 0 else - 1
if __name__ = = "__main__" :
main()
# This code is contributed by shubhamsingh |
// Javascript code to implement the approach // Function to find lines crossed by the point function minimumLines(N, points, Q, X_coordinate, Y_coordinate)
{ // TreeSet for storing points
let set = new Set();
// HashMap for storing points and their index
hash = {};
// Loop for initializing TreeSet and HashMap
for (let i = 0; i < N; i++)
{
let val = points[i];
set.add(val);
hash[val] = i;
}
// Loop for number of times Query asked
for (let i = 0; i < Q; i++) {
// X coordinate
x = X_coordinate[i];
// Y coordinate
y = Y_coordinate[i];
// Sum of both coordinates
sum = x + y;
// Variable to store minimum number of
// lines
ans = 0;
// Checking if sum exists in HashMap or not
if (hash[sum]) {
// Printing -1 as output.
ans = -1;
console.log(ans);
continue ;
}
// Checking floor value of sum
let [floor, val] = lowerBound(set, sum)
// Printing number of lines needed
// to cross by getting floor value
// of sum
if (floor >= 0){
ind = hash[val]
ans = ind + 1
}
console.log(ans);
}
} function lowerBound(Set, Sum)
{ lb = -1
Set = [...Set].sort()
for (let val in Set){
if (val < Sum){
lb += 1
}
else {
break
}
}
return [lb, lb >=0 ? Set[lb] : -1]
} // Driver Code N = 3; points = [ 1, 2, 5 ]; Q = 3; // X and Y coordinates of Q queries // formally Q number of (X, Y) points X_coordinate = [ 0, 1, 3 ]; Y_coordinate = [ 0, 1, 4 ]; // Function call minimumLines(N, points, Q, X_coordinate,Y_coordinate); // This code is contributed by Shubham SIngh. |
using System;
using System.Collections.Generic;
class GFG {
static void Main( string [] args)
{
int N = 3;
int [] points = { 1, 2, 5 };
int Q = 3;
// X and Y coordinates of Q queries
// formally Q number of (X, Y) points
int [] X_coordinate = { 0, 1, 3 };
int [] Y_coordinate = { 0, 1, 4 };
// Function call
minimumLines(N, points, Q, X_coordinate,
Y_coordinate);
}
// Function to find lines crossed by the point
static void minimumLines( int N, int [] points, int Q,
int [] X_coordinate,
int [] Y_coordinate)
{
// TreeSet for storing points
SortedSet< long > set = new SortedSet< long >();
// HashMap for storing points and their index
Dictionary< long , int > hash
= new Dictionary< long , int >();
// Loop for initializing TreeSet and HashMap
for ( int i = 0; i < N; i++) {
long val = points[i];
set .Add(val);
hash.Add(val, i);
}
// Loop for number of times Query asked
for ( int i = 0; i < Q; i++) {
// X coordinate
int x = X_coordinate[i];
// Y coordinate
int y = Y_coordinate[i];
// Sum of both coordinates
long sum = x + y;
// Variable to store minimum number of
// lines
int ans = 0;
// Checking if sum exists in HashMap or not
if (hash.ContainsKey(sum)) {
// Printing -1 as output.
ans = -1;
Console.WriteLine(ans);
continue ;
}
// Checking floor value of sum
long floor
= set .GetViewBetween( long .MinValue, sum)
.Max;
// Printing number of lines needed
// to cross by getting floor value
// of sum
if (floor != 0) {
int ind = hash[floor];
ans = ind + 1;
}
Console.WriteLine(ans);
}
}
} |
0 -1 3
Time Complexity: O(log(N))
Auxiliary Space: O(N)
Another Approach: using Binary Search
- First, we need to create a TreeSet and HashMap in order to store the points.
- Traverse through each point and insert it into the TreeSet and HashMap respectively. In the HashMap, store each point along with its index.
- Run a loop for Q number of times, where Q is the number of queries.
- For each query, get the X and Y coordinates.
- Calculate the sum of X and Y coordinates.
- If the HashMap contains the sum, return -1 as the output.
- Else, get the floor value of the sum from the TreeSet.
- If the floor value is not null, get its index from the HashMap.
- Return the index + 1 as the minimum number of lines to cross to reach the origin.
- Repeat the above steps for all queries.
- Finally, output the minimum number of lines for each query.
Implementation takes input as follows:
- N: The number of integers in the sorted format.
- points[]: An array containing N integers.
- Q: The number of queries to be performed.
- X_coordinate[]: An array containing X-coordinates for each query.
- Y_coordinate[]: An array containing Y-coordinates for each query.
Below is the implementation of the above approach:
#include <bits/stdc++.h> using namespace std;
// Function to find lines crossed by the point void minimumLines( int N, int points[], int Q,
int X_coordinate[], int Y_coordinate[])
{ // TreeSet for storing points
set< int > set;
// HashMap for storing points and their index
unordered_map< int , int > hash;
// Loop for initializing TreeSet and HashMap
for ( int i = 0; i < N; i++) {
int val = points[i];
set.insert(val);
hash[val] = i;
}
// Loop for number of times Query asked
for ( int i = 0; i < Q; i++) {
// X coordinate
int x = X_coordinate[i];
// Y coordinate
int y = Y_coordinate[i];
// Sum of both coordinates
long sum = x + y;
// Variable to store minimum number of
// lines
int ans = 0;
// Checking if sum exists in HashMap or not
if (hash[sum]) {
// Printing -1 as output.
ans = -1;
cout << (ans) << endl;
continue ;
}
// Checking floor value of sum
auto floor = --set.upper_bound(sum);
// Printing number of lines needed
// to cross by getting floor value
// of sum
if ( floor != set.end()) {
int ind = hash[* floor ];
ans = ind + 1;
}
cout << ans << endl;
}
} // Driver Code int main()
{ int N = 3;
int points[] = { 1, 2, 5 };
int Q = 3;
// X and Y coordinates of Q queries
// formally Q number of (X, Y) points
int X_coordinate[] = { 0, 1, 3 };
int Y_coordinate[] = { 0, 1, 4 };
minimumLines(N, points, Q, X_coordinate, Y_coordinate);
return 0;
} |
// Java code for above approach import java.util.*;
class Main {
// Function to find lines crossed by the point static void minimumLines( int N, int points[], int Q,
int X_coordinate[], int Y_coordinate[])
{ // TreeSet for storing points
NavigableSet<Integer> set = new TreeSet<>();
// HashMap for storing points and their index
HashMap<Integer, Integer> hash = new HashMap<>();
// Loop for initializing TreeSet and HashMap
for ( int i = 0 ; i < N; i++) {
int val = points[i];
set.add(val);
hash.put(val, i);
}
// Loop for number of times Query asked
for ( int i = 0 ; i < Q; i++) {
// X coordinate
int x = X_coordinate[i];
// Y coordinate
int y = Y_coordinate[i];
// Sum of both coordinates
long sum = x + y;
// Variable to store minimum number of
// lines
int ans = 0 ;
// Checking if sum exists in HashMap or not
if (hash.containsKey(( int )sum)) {
// Printing -1 as output.
ans = - 1 ;
System.out.println(ans);
continue ;
}
// Checking floor value of sum
Integer floor = set.floor(( int )sum);
// Printing number of lines needed
// to cross by getting floor value
// of sum
if (floor != null ) {
int ind = hash.get(floor);
ans = ind + 1 ;
}
System.out.println(ans);
}
} // Driver Code public static void main(String[] args)
{ int N = 3 ;
int points[] = { 1 , 2 , 5 };
int Q = 3 ;
// X and Y coordinates of Q queries
// formally Q number of (X, Y) points
int X_coordinate[] = { 0 , 1 , 3 };
int Y_coordinate[] = { 0 , 1 , 4 };
minimumLines(N, points, Q, X_coordinate, Y_coordinate);
} } // This code is contributed Utkarsh Kumar. |
def minimumLines(N, points, Q, X_coordinate, Y_coordinate):
# Set for storing points
set1 = set ()
# Hashmap for storing points and their index
hash1 = {}
# Loop for initializing Set and hashmap
for i in range (N):
val = points[i]
set1.add(val)
hash1[val] = i
# Loop for number of times Query asked
for i in range (Q):
# X coordinate
x = X_coordinate[i]
# Y coordinate
y = Y_coordinate[i]
# Sum of both coordinates
sum1 = x + y
# Variable to store minimum number of lines
ans = 0
# Checking if sum exists in hashmap or not
if sum1 in hash1:
# Printing -1 as output.
ans = - 1
print (ans)
continue
# Checking floor value of sum
floor_list = [e for e in set1 if e < sum1]
floor = floor_list[ - 1 ] if floor_list else None
# Printing number of lines needed
# to cross by getting floor value
# of sum
if floor ! = None :
ind = hash1[floor]
ans = ind + 1
print (ans)
# Driver Code N = 3
points = [ 1 , 2 , 5 ]
Q = 3
# X and Y coordinates of Q queries # formally Q number of (X, Y) points X_coordinate = [ 0 , 1 , 3 ]
Y_coordinate = [ 0 , 1 , 4 ]
minimumLines(N, points, Q, X_coordinate, Y_coordinate) |
using System;
using System.Collections.Generic;
class Program {
// Function to find lines crossed by the point
static void MinimumLines( int N, int [] points, int Q,
int [] X_coordinate, int [] Y_coordinate) {
// TreeSet for storing points
SortedSet< int > set = new SortedSet< int >();
// Dictionary for storing points and their index
Dictionary< int , int > hash = new Dictionary< int , int >();
// Loop for initializing TreeSet and HashMap
for ( int i = 0; i < N; i++) {
int val = points[i];
set .Add(val);
hash[val] = i;
}
// Loop for number of times Query asked
for ( int i = 0; i < Q; i++) {
// X coordinate
int x = X_coordinate[i];
// Y coordinate
int y = Y_coordinate[i];
// Sum of both coordinates
long sum = x + y;
// Variable to store minimum number of
// lines
int ans = 0;
// Checking if sum exists in Dictionary or not
if (hash.ContainsKey(( int )sum)) {
// Printing -1 as output.
ans = -1;
Console.WriteLine(ans+ " " );
continue ;
}
// Checking floor value of sum
var floor = set .GetViewBetween( int .MinValue, ( int )(sum - 1)).Max;
// Printing number of lines needed
// to cross by getting floor value
// of sum
if (floor != int .MaxValue && hash.ContainsKey(floor)) {
int ind = hash[floor];
ans = ind + 1;
}
Console.WriteLine(ans+ " " );
}
}
// Driver Code
static void Main( string [] args) {
int N = 3;
int [] points = { 1, 2, 5 };
int Q = 3;
// X and Y coordinates of Q queries
// formally Q number of (X, Y) points
int [] X_coordinate = { 0, 1, 3 };
int [] Y_coordinate = { 0, 1, 4 };
MinimumLines(N, points, Q, X_coordinate, Y_coordinate);
}
} |
function minimumLines(N, points, Q, X_coordinate, Y_coordinate) {
// Set for storing points
let set = new Set();
// Map for storing points and their index
let hash = new Map();
// Loop for initializing Set and Map
for (let i = 0; i < N; i++) {
let val = points[i];
set.add(val);
hash.set(val, i);
}
// Loop for number of times Query asked
for (let i = 0; i < Q; i++) {
// X coordinate
let x = X_coordinate[i];
// Y coordinate
let y = Y_coordinate[i];
// Sum of both coordinates
let sum = x + y;
// Variable to store minimum number of lines
let ans = 0;
// Checking if sum exists in Map or not
if (hash.has(sum)) {
// Printing -1 as output.
ans = -1;
console.log(ans);
continue ;
}
// Checking floor value of sum
let floor = Array.from(set).filter(e => e < sum).pop();
// Printing number of lines needed
// to cross by getting floor value
// of sum
if (floor !== undefined) {
let ind = hash.get(floor);
ans = ind + 1;
}
console.log(ans);
}
} // Driver Code let N = 3; let points = [ 1, 2, 5 ]; let Q = 3; // X and Y coordinates of Q queries // formally Q number of (X, Y) points let X_coordinate = [ 0, 1, 3 ]; let Y_coordinate = [ 0, 1, 4 ]; minimumLines(N, points, Q, X_coordinate, Y_coordinate); |
0 -1 3
Time Complexity: O(Q * log N)
Auxiliary Space: O(N)