Open In App

Minimum difference between values in an array with factors 1 to M

Last Updated : 03 Apr, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given an array of nums of length N and an integer M, the task is to find the minimum difference between two elements of nums such that the numbers coming between these two integers (including the selected numbers) have all factors 1, 2, 3, …, M. Return the minimum difference if it does not exist then return -1.

Examples:

Input: N = 5, M = 7, nums = [6, 4, 5, 3, 7]
Output: 3
Explanation: First number will be 4 and the second will be 7, so the numbers between 4 and 7 are: [4, 5, 7]
Factors of 4 –> (1, 2, 4)
Factors of 5 –> (1, 5)
Factors of 7 –> (1, 7)
So, it contains every number from 1, 2, 3, 4, 5, 6, 7(as M = 7)

Input: N = 4, M = 2, nums = [3, 7, 2, 9]
Output: 0
Explanation: First number will be 2 and Second number is also 2
Factors of 2 –> (1, 2)
So it contains 1, 2(as M = 2)

Input: N = 3, M = 4, nums = [1, 3, 7]
Output: -1

Approach: To solve the problem follow the below-given steps:

  • Sort the given array in a non-decreasing array
  • Find factors of every number present in the given array.
  • Now we will use two pointer approach to solve the problem and we will keep track of factors in Hash Map factorFreq.
  • Start from the 0th index for both the ith and jth pointer.
  • Now while factorFreq size is less than M, we will keep incrementing the jth pointer.
  • If the size of factorFreq is equal to M then compare the difference between the jth value and ith value and increment the ith value, make sure you don’t forget to update the factorFreq.
  • Return the min value if exist.

Below is the implementation of the above approach:

C++




#include <bits/stdc++.h>
 
using namespace std;
 
// Function to find the factors of a given integer
vector<int> factorsOfNumber(int n)
{
    vector<int> factors = { 1 };
    if (n == 1)
        return factors;
    for (int i = 2; i * i <= n; i++) {
        if (n % i == 0) {
            if (n / i == i) {
                factors.push_back(i);
            }
            else {
                factors.push_back(i);
                factors.push_back(n / i);
            }
        }
    }
    factors.push_back(n);
    return factors;
}
 
// Function to find the minimum difference of two selected
// integers
int findMinDifference(int nums[], int N, int M)
{
 
    // Sorting given array
    sort(nums, nums + N);
 
    // Factors will contain the
    // factors of the given integers
    // in nums array
    vector<int> factors[N];
    for (int i = 0; i < N; i++) {
        factors[i] = factorsOfNumber(nums[i]);
    }
 
    // factorFreq will map the
    // frequency of factors which is
    // less than or equal to M
    map<int, int> factorFreq;
    int i = 0;
    int j = 0;
 
    // minDiff will contain our
    // final answer
    int minDiff = INT_MAX;
 
    // Using two pointer
    while (i < N && j < N) {
 
        // If factorFreq size is equal
        // to M, then we can increment
        // the pointer i
        if (factorFreq.size() == M) {
 
            // Updating minDiff
            minDiff = min(minDiff, (nums[j - 1] - nums[i]));
 
            // Updating factorFreq
            for (int k = 0; k < factors[i].size(); k++) {
                if (factors[i][k] <= M) {
                    factorFreq[factors[i][k]]--;
                    if (factorFreq[factors[i][k]] == 0)
                        factorFreq.erase(factors[i][k]);
                }
            }
            i++;
        }
 
        // Otherwise we will increment
        // the j pointer
        else {
 
            // Updating factorFreq
            for (int k = 0; k < factors[j].size(); k++) {
                if (factors[j][k] <= M) {
                    factorFreq[factors[j][k]]++;
                }
            }
            j++;
        }
    }
 
    // Checking if i<N but factorFreq
    // size is still equal to M, means
    // we can still increment i
    while (i < N && factorFreq.size() == M) {
        minDiff = min(minDiff, (nums[j - 1] - nums[i]));
        for (int k = 0; k < factors[i].size(); k++) {
            if (factors[i][k] <= M) {
                factorFreq[factors[i][k]]--;
                if (factorFreq[factors[i][k]] == 0)
                    factorFreq.erase(factors[i][k]);
            }
        }
        i++;
    }
 
    // Check if two numbers exist or
    // not and return the value
    if (minDiff == INT_MAX)
        return -1;
    else
        return minDiff;
}
 
// Driver code
int main()
{
    int N = 5;
    int M = 7;
    int nums[] = { 6, 4, 5, 3, 7 };
    cout << findMinDifference(nums, N, M) << endl;
    return 0;
}


Java




// Java algorithm for the above approach
 
import java.util.*;
 
class GFG {
 
    // Driver Code
    public static void main(String[] args)
    {
        int N = 5;
        int M = 7;
        int[] nums = { 6, 4, 5, 3, 7 };
        System.out.println(findMinDifference(nums, N, M));
    }
 
    // Function to find the minimum
    // Difference of two selected integers
    public static int findMinDifference(int[] nums, int N,
                                        int M)
    {
 
        // Sorting given array
        Arrays.sort(nums);
 
        // Factors will contain the
        // factors of the given integers
        // in nums array
        List<Integer>[] factors = new ArrayList[N];
        for (int i = 0; i < N; i++) {
            factors[i] = factorsOfNumber(nums[i]);
        }
 
        // factorFreq will map the
        // frequency of factors which is
        // less than or equal to M
        Map<Integer, Integer> factorFreq = new HashMap<>();
        int i = 0;
        int j = 0;
 
        // minDiff will contain our
        // final answer
        int minDiff = Integer.MAX_VALUE;
 
        // Using two pointer
        while (i < N && j < N) {
 
            // If factorFreq size is equal
            // to M, then we can increment
            // the pointer i
            if (factorFreq.size() == M) {
 
                // Updating minDiff
                minDiff = Math.min(minDiff,
                                   (nums[j - 1] - nums[i]));
                // Updating factorFreq
                for (int k = 0; k < factors[i].size();
                     k++) {
                    if (factors[i].get(k) <= M) {
                        factorFreq.put(
                            factors[i].get(k),
                            factorFreq.get(
                                factors[i].get(k))
                                - 1);
                        if (factorFreq.get(
                                factors[i].get(k))
                            == 0)
                            factorFreq.remove(
                                factors[i].get(k));
                    }
                }
                i++;
            }
 
            // Otherwise we will increment
            // the j pointer
            else {
 
                // Updating factorFreq
                for (int k = 0; k < factors[j].size();
                     k++) {
                    if (factors[j].get(k) <= M) {
                        factorFreq.put(
                            factors[j].get(k),
                            factorFreq.getOrDefault(
                                factors[j].get(k), 0)
                                + 1);
                    }
                }
 
                j++;
            }
        }
 
        // Checking if i<N bus factorFreq
        // size is still equal to M, means
        // we can still increment i
        while (i < N && factorFreq.size() == M) {
            minDiff = Math.min(minDiff,
                               (nums[j - 1] - nums[i]));
            for (int k = 0; k < factors[i].size(); k++) {
                if (factors[i].get(k) <= M) {
                    factorFreq.put(
                        factors[i].get(k),
                        factorFreq.get(factors[i].get(k))
                            - 1);
                    if (factorFreq.get(factors[i].get(k))
                        == 0)
                        factorFreq.remove(
                            factors[i].get(k));
                }
            }
            i++;
        }
 
        // Check if two numbers exist or
        // not and return the value
        if (minDiff == Integer.MAX_VALUE)
            return -1;
        else
            return minDiff;
    }
 
    // Function tpo find the factor
    // of the given integer
    public static List<Integer> factorsOfNumber(int n)
    {
        List<Integer> fact = new ArrayList<>();
        fact.add(1);
        if (n == 1)
            return fact;
        for (int i = 2; i * i <= n; i++) {
            if (n % i == 0) {
                if (n / i == i) {
                    fact.add(i);
                }
                else {
                    fact.add(i);
                    fact.add(n / i);
                }
            }
        }
 
        fact.add(n);
        return fact;
    }
}


Python3




# Python code implementation:
 
import math
from collections import defaultdict
 
def findMinDifference(nums, N, M):
 
    # Sorting given array
    nums.sort()
 
    # Factors will contain the factors of the given integers
    # in nums array
    factors = []
    for i in range(N):
        factors.append(factorsOfNumber(nums[i]))
 
    # factorFreq will map the frequency of factors which is
    # less than or equal to M
    factorFreq = defaultdict(int)
    i = 0
    j = 0
 
    # minDiff will contain our final answer
    minDiff = math.inf
 
    # Using two pointer
    while i < N and j < N:
 
        # If factorFreq size is equal to M, then we can
        # increment the pointer i
        if len(factorFreq) == M:
 
            # Updating minDiff
            minDiff = min(minDiff, nums[j-1] - nums[i])
 
            # Updating factorFreq
            for k in range(len(factors[i])):
                if factors[i][k] <= M:
                    factorFreq[factors[i][k]] -= 1
                    if factorFreq[factors[i][k]] == 0:
                        del factorFreq[factors[i][k]]
 
            i += 1
 
        # Otherwise we will increment the j pointer
        else:
 
            # Updating factorFreq
            for k in range(len(factors[j])):
                if factors[j][k] <= M:
                    factorFreq[factors[j][k]] += 1
 
            j += 1
 
    # Checking if i<N bus factorFreq size is still equal
    # to M, means we can still increment i
    while i < N and len(factorFreq) == M:
        minDiff = min(minDiff, nums[j-1] - nums[i])
 
        for k in range(len(factors[i])):
            if factors[i][k] <= M:
                factorFreq[factors[i][k]] -= 1
                if factorFreq[factors[i][k]] == 0:
                    del factorFreq[factors[i][k]]
 
        i += 1
 
    # Check if two numbers exist or not and return the value
    if minDiff == math.inf:
        return -1
    else:
        return minDiff
 
 
# Function to find the factor of the given integer
def factorsOfNumber(n):
    fact = [1]
    if n == 1:
        return fact
 
    for i in range(2, int(math.sqrt(n))+1):
        if n % i == 0:
            if n // i == i:
                fact.append(i)
            else:
                fact.append(i)
                fact.append(n // i)
 
    fact.append(n)
    return fact
 
 
N = 5
M = 7
nums = [6, 4, 5, 3, 7]
print(findMinDifference(nums, N, M))
 
# This code is contributed by lokesh.


C#




// C# code for the approach
using System;
using System.Collections.Generic;
using System.Linq;
 
class GFG {
      // Driver's code
    static void Main(string[] args)
    {
          // Input
        int N = 5;
        int M = 7;
        int[] nums = { 6, 4, 5, 3, 7 };
           
          // Function call
        Console.WriteLine(findMinDifference(nums, N, M));
    }
 
    // Function to find the factors of a given integer
    static List<int> factorsOfNumber(int n)
    {
        List<int> factors = new List<int>{ 1 };
        if (n == 1)
            return factors;
        for (int i = 2; i * i <= n; i++) {
            if (n % i == 0) {
                if (n / i == i) {
                    factors.Add(i);
                }
                else {
                    factors.Add(i);
                    factors.Add(n / i);
                }
            }
        }
        factors.Add(n);
        return factors;
    }
     
      // Function to find the minimum difference of two selected
    // integers
    static int findMinDifference(int[] nums, int N, int M)
    {
        // Sorting given array
        Array.Sort(nums);
 
        // Factors will contain the factors of the given
        // integers in nums array
        List<List<int> > factors = new List<List<int> >();
        for (int k = 0; k < N; k++) {
            factors.Add(factorsOfNumber(nums[k]));
        }
 
        // factorFreq will map the frequency of factors
        // which is less than or equal to M
        Dictionary<int, int> factorFreq
            = new Dictionary<int, int>();
        int i = 0;
        int j = 0;
 
        // minDiff will contain our final answer
        int minDiff = int.MaxValue;
 
        // Using two pointer
        while (i < N && j < N) {
            // If factorFreq size is equal to M, then we can
            // increment the pointer i
            if (factorFreq.Count == M) {
                // Updating minDiff
                minDiff = Math.Min(minDiff,
                                   nums[j - 1] - nums[i]);
 
                // Updating factorFreq
                for (int k = 0; k < factors[i].Count; k++) {
                    if (factors[i][k] <= M) {
                        factorFreq[factors[i][k]] -= 1;
                        if (factorFreq[factors[i][k]]
                            == 0) {
                            factorFreq.Remove(
                                factors[i][k]);
                        }
                    }
                }
 
                i += 1;
            }
 
            // Otherwise we will increment the j pointer
            else {
                // Updating factorFreq
                for (int k = 0; k < factors[j].Count; k++) {
                    if (factors[j][k] <= M) {
                        if (factorFreq.ContainsKey(
                                factors[j][k])) {
                            factorFreq[factors[j][k]] += 1;
                        }
                        else {
                            factorFreq.Add(factors[j][k],
                                           1);
                        }
                    }
                }
 
                j += 1;
            }
        }
 
        // Checking if i<N bus factorFreq size is still
        // equal to M, means we can still increment i
        while (i < N && factorFreq.Count == M) {
            minDiff
                = Math.Min(minDiff, nums[j - 1] - nums[i]);
 
            for (int k = 0; k < factors[i].Count; k++) {
                if (factors[i][k] <= M) {
                    factorFreq[factors[i][k]] -= 1;
                    if (factorFreq[factors[i][k]] == 0) {
                        factorFreq.Remove(factors[i][k]);
                    }
                }
            }
 
            i += 1;
        }
 
        // Check if two numbers exist or not and return the
        // value
        if (minDiff == int.MaxValue)
            return -1;
        else
            return minDiff;
    }
}


Javascript




// Javascript code implementation
 
function findMinDifference(nums, N, M){
// Sorting given array
nums.sort(function(a, b){return a - b});
 
// Factors will contain the factors of the given integers
// in nums array
var factors = [];
for (var i = 0; i < N; i++){
    factors.push(factorsOfNumber(nums[i]));
}
 
// factorFreq will map the frequency of factors which is
// less than or equal to M
var factorFreq = {};
var i = 0;
var j = 0;
 
// minDiff will contain our final answer
var minDiff = Infinity;
 
// Using two pointer
while (i < N && j < N){
 
    // If factorFreq size is equal to M, then we can
    // increment the pointer i
    if (Object.keys(factorFreq).length === M){
 
        // Updating minDiff
        minDiff = Math.min(minDiff, nums[j-1] - nums[i]);
 
        // Updating factorFreq
        for (var k = 0; k < factors[i].length; k++){
            if (factors[i][k] <= M){
                factorFreq[factors[i][k]] -= 1;
                if (factorFreq[factors[i][k]] === 0){
                    delete factorFreq[factors[i][k]];
                }
            }
        }
 
        i += 1;
 
    // Otherwise we will increment the j pointer
    } else {
 
        // Updating factorFreq
        for (var k = 0; k < factors[j].length; k++){
            if (factors[j][k] <= M){
                if (factorFreq[factors[j][k]]){
                    factorFreq[factors[j][k]] += 1;
                } else {
                    factorFreq[factors[j][k]] = 1;
                }
            }
        }
 
        j += 1;
 
    }
}
 
// Checking if i<N bus factorFreq size is still equal
// to M, means we can still increment i
while (i < N && Object.keys(factorFreq).length === M){
    minDiff = Math.min(minDiff, nums[j-1] - nums[i]);
 
    for (var k = 0; k < factors[i].length; k++){
        if (factors[i][k] <= M){
            factorFreq[factors[i][k]] -= 1;
            if (factorFreq[factors[i][k]] === 0){
                delete factorFreq[factors[i][k]];
            }
        }
    }
 
    i += 1;
}
 
// Check if two numbers exist or not and return the value
if (minDiff === Infinity){
    return -1;
} else {
    return minDiff;
}
}
 
// Function to find the factor of the given integer
function factorsOfNumber(n){
var fact = [1];
if (n === 1){
return fact;
}
for (var i = 2; i <= Math.floor(Math.sqrt(n)); i++){
    if (n % i === 0){
        if (n / i === i){
            fact.push(i);
        } else {
            fact.push(i);
            fact.push(n / i);
        }
    }
}
 
fact.push(n);
return fact;
}
 
var N = 5;
var M = 7;
var nums = [6, 4, 5, 3, 7];
console.log(findMinDifference(nums, N, M));


Output

3

Time Complexity: O(N* sqrt(N))
Auxiliary Space: O(N * sqrt(N))



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads