Check if all array elements can be reduced to less than X
Given an array A[] consisting of N positive integers and an integer X, the task is to determine if it is possible to convert all array elements to less than X by performing the following operations:
- Select 2 distinct indices j and k.
- Select an index i, where A[i] > X.
- Replace A[i] = gcd(A[j], A[k]) if and only if gcd(A[j], A[k]) ? 1.
Examples:
Input: A[] = {2, 1, 5, 3, 6}, X = 4
Output: Yes
Explanation:
- Selecting i = 3, j = 4, k = 5, set A[i] = gcd(A[j], A[k]) = 3. Therefore, A[] modifies to {2, 1, 3, 3, 6}.
- Selecting i = 5, j = 4, k = 5, set A[i] = gcd(A[j], A[k]) = 3. Therefore, A[] modifies to {2, 1, 3, 3, 3}.
Input: A[] = {2, 3, 2, 5, 4}, X = 3
Output: Yes
Approach: Follow the steps below to solve the problem:
- Find the two numbers having gcd ? 1 as well as gcd ? X, then, by using these two numbers, the required number A[i] can be replaced with gcd(A[j], A[k]).
- Using the fact that gcd(x, y) ? min(x, y), the array elements can be reduced to ? X.
- This way, the rest of the array can be converted to ? X using step 2.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
bool check( int A[], int X, int N)
{
for ( int i = 0; i < N; i++)
{
if (A[i] > X)
{
return false ;
}
}
return true ;
}
bool findAns( int A[], int N, int X)
{
if (check(A, X, N))
{
return true ;
}
for ( int i = 0; i < N; i++)
{
for ( int j = i + 1; j < N; j++)
{
int g = __gcd(A[i], A[j]);
if (g != 1)
{
if (g <= X)
{
return true ;
}
}
}
}
return false ;
}
int main()
{
int X = 4;
int A[] = { 2, 1, 5, 3, 6 };
int N = 5;
if (findAns(A, N, X))
{
cout << "true" ;
}
else
{
cout << "false" ;
}
}
|
Java
import java.io.*;
import java.util.Arrays;
class GFG {
public static boolean findAns(
int [] A, int N, int X)
{
if (check(A, X)) {
return true ;
}
for ( int i = 0 ; i < N; i++) {
for ( int j = i + 1 ; j < N; j++) {
int gcd = gcd(A[i], A[j]);
if (gcd != 1 ) {
if (gcd <= X) {
return true ;
}
}
}
}
return false ;
}
public static boolean check( int [] A, int X)
{
for ( int i = 0 ; i < A.length; i++) {
if (A[i] > X) {
return false ;
}
}
return true ;
}
public static int gcd( int a, int b)
{
if (b == 0 )
return a;
return gcd(b, a % b);
}
public static void main(String[] args)
{
int X = 4 ;
int [] A = { 2 , 1 , 5 , 3 , 6 };
int N = 5 ;
System.out.println(findAns(A, N, X));
}
}
|
Python3
def findAns(A, N, X):
if (check(A, X)):
return True
for i in range (N):
for j in range (i + 1 , N):
gcd = GCD(A[i], A[j])
if (gcd ! = 1 ):
if (gcd < = X):
return True
return False
def check(A, X):
for i in range ( len (A)):
if (A[i] > X):
return False
return True
def GCD(a, b):
if (b = = 0 ):
return a
return GCD(b, a % b)
X = 4
A = [ 2 , 1 , 5 , 3 , 6 ]
N = 5
print (findAns(A, N, X))
|
C#
using System;
class GFG {
public static bool findAns(
int [] A, int N, int X)
{
if (check(A, X))
{
return true ;
}
for ( int i = 0; i < N; i++)
{
for ( int j = i + 1; j < N; j++)
{
int gcd = gcdFoo(A[i], A[j]);
if (gcd != 1)
{
if (gcd <= X)
{
return true ;
}
}
}
}
return false ;
}
public static bool check( int [] A, int X)
{
for ( int i = 0; i < A.Length; i++)
{
if (A[i] > X)
{
return false ;
}
}
return true ;
}
static int gcdFoo( int a, int b)
{
if (b == 0)
return a;
return gcdFoo(b, a % b);
}
public static void Main(String[] args)
{
int X = 4;
int [] A = { 2, 1, 5, 3, 6 };
int N = 5;
Console.WriteLine(findAns(A, N, X));
}
}
|
Javascript
<script>
function findAns(
A, N, X)
{
if (check(A, X)) {
return true ;
}
for (let i = 0; i < N; i++) {
for (let j = i + 1; j < N; j++) {
let gcdd = gcd(A[i], A[j]);
if (gcdd != 1) {
if (gcdd <= X) {
return true ;
}
}
}
}
return false ;
}
function check(A, X)
{
for (let i = 0; i < A.length; i++) {
if (A[i] > X) {
return false ;
}
}
return true ;
}
function gcd(a, b)
{
if (b == 0)
return a;
return gcd(b, a % b);
}
let X = 4;
let A = [ 2, 1, 5, 3, 6 ];
let N = 5;
document.write(findAns(A, N, X));
</script>
|
Time Complexity: O(N2)
Auxiliary Space: O(1)
New Approach:- Here, Another approach to solve this problem is by using Binary Search. We can perform a binary search on the range of possible values for the final array. We can set the lower bound to be 1 and the upper bound to be the maximum value in the array. For each mid value, we can check if it is possible to reduce all the array elements to less than or equal to this value.
To check this, we can iterate over all pairs of elements in the array and check if their gcd is either 1 or less than or equal to the mid value. If we find such a pair, we can update the value of mid to be the gcd of this pair.
If we find a mid value for which it is possible to reduce all array elements to less than or equal to this value, we can move the upper bound to mid. Otherwise, we can move the lower bound to mid + 1.
Below is the implementation of this approach:
C++
#include <bits/stdc++.h>
using namespace std;
bool canReduce( int A[], int N, int X) {
for ( int i = 0; i < N; i++) {
if (A[i] > X) {
bool foundPair = false ;
for ( int j = 0; j < N; j++) {
for ( int k = j + 1; k < N; k++) {
int gcd = __gcd(A[j], A[k]);
if (gcd != 1 && gcd <= X) {
foundPair = true ;
X = gcd;
break ;
}
}
if (foundPair) {
break ;
}
}
if (!foundPair) {
return false ;
}
}
}
return true ;
}
bool findAns( int A[], int N, int X) {
int low = 1;
int high = *max_element(A, A + N);
while (low < high) {
int mid = low + (high - low) / 2;
if (canReduce(A, N, mid)) {
high = mid;
} else {
low = mid + 1;
}
}
return canReduce(A, N, low);
}
int main() {
int X = 4;
int A[] = { 2, 1, 5, 3, 6 };
int N = 5;
if (findAns(A, N, X)) {
cout << "true" ;
} else {
cout << "false" ;
}
return 0;
}
|
Java
import java.util.*;
public class Main {
public static void main(String[] args) {
int X = 4 ;
int [] A = { 2 , 1 , 5 , 3 , 6 };
int N = 5 ;
if (findAns(A, N, X)) {
System.out.println( "true" );
} else {
System.out.println( "false" );
}
}
public static boolean canReduce( int [] A, int N, int X) {
for ( int i = 0 ; i < N; i++) {
if (A[i] > X) {
boolean foundPair = false ;
for ( int j = 0 ; j < N; j++) {
for ( int k = j + 1 ; k < N; k++) {
int gcd = gcd(A[j], A[k]);
if (gcd != 1 && gcd <= X) {
foundPair = true ;
X = gcd;
break ;
}
}
if (foundPair) {
break ;
}
}
if (!foundPair) {
return false ;
}
}
}
return true ;
}
public static boolean findAns( int [] A, int N, int X) {
int low = 1 ;
int high = Arrays.stream(A).max().getAsInt();
while (low < high) {
int mid = low + (high - low) / 2 ;
if (canReduce(A, N, mid)) {
high = mid;
} else {
low = mid + 1 ;
}
}
return canReduce(A, N, low);
}
public static int gcd( int a, int b) {
if (b == 0 ) {
return a;
}
return gcd(b, a % b);
}
}
|
Python3
import math
def canReduce(A, N, X):
for i in range (N):
if A[i] > X:
foundPair = False
for j in range (N):
for k in range (j + 1 , N):
gcd = math.gcd(A[j], A[k])
if gcd ! = 1 and gcd < = X:
foundPair = True
X = gcd
break
if foundPair:
break
if not foundPair:
return False
return True
def findAns(A, N, X):
low = 1
high = max (A)
while low < high:
mid = low + (high - low) / / 2
if canReduce(A, N, mid):
high = mid
else :
low = mid + 1
return canReduce(A, N, low)
if __name__ = = '__main__' :
X = 4
A = [ 2 , 1 , 5 , 3 , 6 ]
N = 5
if findAns(A, N, X):
print ( "true" )
else :
print ( "false" )
|
C#
using System;
using System.Linq;
public class ArrayReduction
{
static bool CanReduce( int [] A, int N, int X)
{
for ( int i = 0; i < N; i++)
{
if (A[i] > X)
{
bool foundPair = false ;
for ( int j = 0; j < N; j++)
{
for ( int k = j + 1; k < N; k++)
{
int gcd = GCD(A[j], A[k]);
if (gcd != 1 && gcd <= X)
{
foundPair = true ;
X = gcd;
break ;
}
}
if (foundPair)
{
break ;
}
}
if (!foundPair)
{
return false ;
}
}
}
return true ;
}
static int GCD( int a, int b)
{
while (b != 0)
{
int temp = b;
b = a % b;
a = temp;
}
return a;
}
static bool FindAns( int [] A, int N, int X)
{
int low = 1;
int high = A.Max();
while (low < high)
{
int mid = low + (high - low) / 2;
if (CanReduce(A, N, mid))
{
high = mid;
}
else
{
low = mid + 1;
}
}
return CanReduce(A, N, low);
}
public static void Main( string [] args)
{
int X = 4;
int [] A = { 2, 1, 5, 3, 6 };
int N = 5;
if (FindAns(A, N, X))
{
Console.WriteLine( "true" );
}
else
{
Console.WriteLine( "false" );
}
}
}
|
Javascript
function canReduce(arr, X) {
for (let i = 0; i < arr.length; i++) {
if (arr[i] > X) {
let foundPair = false ;
for (let j = 0; j < arr.length; j++) {
for (let k = j + 1; k < arr.length; k++) {
let gcd = calculateGCD(arr[j], arr[k]);
if (gcd !== 1 && gcd <= X) {
foundPair = true ;
X = gcd;
break ;
}
}
if (foundPair) {
break ;
}
}
if (!foundPair) {
return false ;
}
}
}
return true ;
}
function calculateGCD(a, b) {
if (b === 0) {
return a;
}
return calculateGCD(b, a % b);
}
function findAns(arr, X) {
let low = 1;
let high = Math.max(...arr);
while (low < high) {
let mid = low + Math.floor((high - low) / 2);
if (canReduce(arr, mid)) {
high = mid;
} else {
low = mid + 1;
}
}
return canReduce(arr, low);
}
const X = 4;
const A = [2, 1, 5, 3, 6];
const N = 5;
if (findAns(A, N, X)) {
console.log( "true" );
} else {
console.log( "false" );
}
|
“Note that the time complexity of this approach is O(N^3 log(max(A))), where N is the length of the array and max(A) is the maximum value in the array. This is because for each mid value, we need to iterate over all pairs of elements in the array, and for each pair, we need to calculate their gcd, which has a worst-case time complexity of O(log(max(A))). The overall space complexity is O(1).”
Time Complexity:- The time complexity of the canReduce function is O(N^3) because it has three nested loops. The outer loop runs N times, and the inner two loops run N(N-1)/2 times, so the total number of iterations is N^3/2.
The time complexity of the findAns function is O(N^4 log MAX), where MAX is the maximum element in the array. This is because the canReduce function is called for each value of mid in the binary search, and the canReduce function has a time complexity of O(N^3). Therefore, the total time complexity is O(N^3 log MAX) for the binary search, plus an additional O(N^3) for the final call to canReduce with the lowest value of X that works.
Auxiliary Space:- The auxiliary space complexity of both functions is O(1), as they do not use any additional data structures that depend on the input size.
Last Updated :
28 Oct, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...