Minimal product subsequence where adjacent elements are separated by a maximum distance of K
Last Updated :
06 Feb, 2023
Given an array arr[] and an integer K, the task is to find out the minimum product of a subsequence where adjacent elements of the subsequence are separated by a maximum distance of K.
Note: The subsequence should include the first and the last element of the array.
Examples:
Input: arr[] = { 1, 2, 3, 4 }, K = 2
Output: 8
The first element in the subsequence is 1. From 1, we can move to either 2 or 3 (since K = 2). We can move to 3 and then to 4 to have a product of 12. However, we can also move to 2 and then to 4 to have a product of 8. Minimal product subsequence = { 1, 2, 4 }
Input: arr[] = { 2, 3 }, K = 2
Output: 6
Naive Approach: A naive approach is to generate all subsequences of the array and maintain a difference of indices between the adjacent elements and find the minimal product subsequence.
Efficient Approach: An efficient approach is to use dynamic programming. Let dp[i] denote the minimum product of elements till index 'i' including arr[i] who are separated by a maximum distance of K. Then dp[i] can be formulated as follows:
dp[i] = arr[i] * min{dp[j]} where j < i and 1 <= i - j <= K.
To calculate dp[i], a window of size K can be maintained and traversed to find the minimum of dp[j] which can then be multiplied to arr[i]. However, this will result in an O(N*K) solution.
To optimize the solution further, values of the product can be stored in an STL set and the minimum value of the product can then be found out in O(log n) time. Since storing products can be a cumbersome task since the product can easily exceed 1018, therefore we will store log values of products since log is a monotonic function and minimization of log values will automatically imply minimization of products.
Below is the implementation of the above approach:
CPP
// C++ implementation of the above approach.
#include <bits/stdc++.h>
#define mp make_pair
#define ll long long
using namespace std;
const int mod = 1000000007;
const int MAX = 100005;
// Function to get the minimum product of subsequence such that
// adjacent elements are separated by a max distance of K
int minimumProductSubsequence(int* arr, int n, int k)
{
multiset<pair<double, int> > s;
ll dp[MAX];
double p[MAX];
dp[0] = arr[0];
p[0] = log(arr[0]);
// multiset will hold pairs
// pair = (log value of product, dp[j] value)
// dp[j] = minimum product % mod
// multiset will be sorted according to log values
// Therefore, corresponding to the minimum log value
// dp[j] value can be obtained.
s.insert(mp(p[0], dp[0]));
// For the first k-sized window.
for (int i = 1; i < k; i++) {
double l = (s.begin())->first;
ll min = (s.begin())->second;
// Update log value by adding previous
// minimum log value
p[i] = log(arr[i]) + l;
// Update dp[i]
dp[i] = (arr[i] * min) % mod;
// Insert it again into the multiset
// since it is within the k-size window
s.insert(mp(p[i], dp[i]));
}
for (int i = k; i < n; i++) {
double l = (s.begin())->first;
ll min = (s.begin())->second;
p[i] = log(arr[i]) + l;
dp[i] = (arr[i] * min) % mod;
// Eliminate previous value which falls out
// of the k-sized window
multiset<pair<double, int> >::iterator it;
it = s.find(mp(p[i - k], dp[i - k]));
s.erase(it);
// Insert newest value to enter in
// the k-sized window.
s.insert(mp(p[i], dp[i]));
}
// dp[n - 1] will have minimum product %
// mod such that adjacent elements are
// separated by a max distance K
return dp[n - 1];
}
// Driver Code
int main()
{
int arr[] = { 1, 2, 3, 4 };
int n = sizeof(arr) / sizeof(arr[0]);
int k = 2;
cout << minimumProductSubsequence(arr, n, k);
return 0;
}
Java
// Java implementation of the above approach.
import java.io.*;
import java.util.*;
class GFG {
static class Pair {
double x;
int y;
Pair(double x, int y)
{
this.x = x;
this.y = y;
}
}
static int mod = 1000000007;
static int MAX = 100005;
// Function to get the minimum product of subsequence
// such that adjacent elements are separated by a max
// distance of K
static int minimumProductSubsequence(int[] arr, int n,
int k)
{
TreeSet<Pair> s
= new TreeSet<>(new Comparator<Pair>() {
public int compare(Pair a, Pair b)
{
return Double.compare(a.x, b.x);
}
});
int[] dp = new int[MAX];
double[] p = new double[MAX];
dp[0] = arr[0];
p[0] = Math.log(arr[0]);
// TreeSet will hold pairs
// pair = (log value of product, dp[j] value)
// dp[j] = minimum product % mod
// TreeSet will be sorted according to log values
// Therefore, corresponding to the minimum log value
// dp[j] value can be obtained.
s.add(new Pair(p[0], dp[0]));
// For the first k-sized window.
for (int i = 1; i < k; i++) {
double l = s.first().x;
int min = s.first().y;
// Update log value by adding previous
// minimum log value
p[i] = Math.log(arr[i]) + l;
// Update dp[i]
dp[i] = (int)((arr[i] * min) % mod);
// Insert it again into the TreeSet
// since it is within the k-size window
s.add(new Pair(p[i], dp[i]));
}
for (int i = k; i < n; i++) {
double l = s.first().x;
int min = s.first().y;
p[i] = Math.log(arr[i]) + l;
dp[i] = (int)((arr[i] * min) % mod);
// Eliminate previous value which falls out
// of the k-sized window
s.remove(new Pair(p[i - k], dp[i - k]));
// Insert newest value to enter in
// the k-sized window.
s.add(new Pair(p[i], dp[i]));
}
// dp[n - 1] will have minimum product %
// mod such that adjacent elements are
// separated by a max distance K
return (int)dp[n - 1];
}
public static void main(String[] args)
{
int[] arr = { 1, 2, 3, 4 };
int n = arr.length;
int k = 2;
System.out.println(
minimumProductSubsequence(arr, n, k));
}
}
// This code is contributed by lokeshmvs21.
Python3
# Python3 implementation of the above approach.
import math
mod = 1000000007;
MAX = 100005;
# Function to get the minimum product of subsequence such that
# adjacent elements are separated by a max distance of K
def minimumProductSubsequence(arr, n, k):
s = []
dp = [0 for i in range(MAX)];
p = [0.0 for i in range(MAX)];
dp[0] = arr[0];
p[0] = math.log(arr[0]);
# multiset will hold pairs
# pair = (log value of product, dp[j] value)
# dp[j] = minimum product % mod
# multiset will be sorted according to log values
# Therefore, corresponding to the minimum log value
# dp[j] value can be obtained.
s.append([p[0], dp[0]]);
s.sort()
# For the first k-sized window.
for i in range(1, k):
l = s[0][0]
min = s[0][1]
# Update log value by adding previous
# minimum log value
p[i] = math.log(arr[i]) + l;
# Update dp[i]
dp[i] = (arr[i] * min) % mod;
# Insert it again into the multiset
# since it is within the k-size window
s.append([p[i], dp[i]]);
s.sort()
for i in range(k, n):
l = s[0][0]
min = s[0][1]
p[i] = math.log(arr[i]) + l;
dp[i] = (arr[i] * min) % mod;
# Eliminate previous value which falls out
# of the k-sized window
if [p[i - k], dp[i - k]] in s:
s.pop(s.index([p[i - k], dp[i - k]]))
# Insert newest value to enter in
# the k-sized window.
s.append([p[i], dp[i]]);
s.sort()
# dp[n - 1] will have minimum product %
# mod such that adjacent elements are
# separated by a max distance K
return dp[n - 1];
# Driver Code
if __name__=='__main__':
arr = [ 1, 2, 3, 4 ]
n = len(arr)
k = 2;
print(minimumProductSubsequence(arr, n, k))
# This code is contributed by rutvik_56
C#
// C# code for the above approach
using System;
using System.Collections.Generic;
class GFG {
static int mod = 1000000007;
static int MAX = 100005;
// Function to get the minimum product of subsequence such that
// adjacent elements are separated by a max distance of K
public static int minimumProductSubsequence(int[] arr, int n, int k) {
SortedSet<Tuple<double, long>> s = new SortedSet<Tuple<double, long>>(
Comparer<Tuple<double, long>>.Create((a, b) => a.Item1.CompareTo(b.Item1))
);
long[] dp= new long[MAX];
double[] p=new double[MAX];
dp[0] = arr[0];
p[0] = Math.Log(arr[0]);
// SortedSet will hold pairs
// pair = (log value of product, dp[j] value)
// dp[j] = minimum product % mod
// SortedSet will be sorted according to log values
// Therefore, corresponding to the minimum log value
// dp[j] value can be obtained.
s.Add(Tuple.Create(p[0], dp[0]));
// For the first k-sized window.
for (int i = 1; i < k; i++) {
double l = s.Min.Item1;
long min = s.Min.Item2;
// Update log value by adding previous
// minimum log value
p[i] = Math.Log(arr[i]) + l;
// Update dp[i]
dp[i] = (arr[i] * min) % mod;
// Insert it again into the SortedSet
// since it is within the k-size window
s.Add(Tuple.Create(p[i], dp[i]));
}
for (int i = k; i < n; i++) {
double l = s.Min.Item1;
long min = s.Min.Item2;
p[i] = Math.Log(arr[i]) + l;
dp[i] = (arr[i] * min) % mod;
// Eliminate previous value which falls out
// of the k-sized window
s.Remove(Tuple.Create(p[i - k], dp[i - k]));
// Insert newest value to enter in
// the k-sized window.
s.Add(Tuple.Create(p[i], dp[i]));
}
// dp[n - 1] will have minimum product %
// mod such that adjacent elements are
// separated by a max distance K
return (int) dp[n - 1];
}
// Driver Code
public static void Main(string[] args) {
int[] arr = { 1, 2, 3, 4 };
int n = arr.Length;
int k = 2;
Console.WriteLine(minimumProductSubsequence(arr, n, k));
}
}
// This code is contributed by lokeshpotta20
JavaScript
// JavaScript implementation of the above approach.
let mod = 1000000007;
let MAX = 100005;
// Function to get the minimum product of subsequence such that
// adjacent elements are separated by a max distance of K
function minimumProductSubsequence(arr, n, k)
{
let s = []
let dp = new Array(MAX).fill(0)
let p = new Array(MAX).fill(0.0)
dp[0] = arr[0];
p[0] = Math.log(arr[0]);
// multiset will hold pairs
// pair = (log value of product, dp[j] value)
// dp[j] = minimum product % mod
// multiset will be sorted according to log values
// Therefore, corresponding to the minimum log value
// dp[j] value can be obtained.
s.push([p[0], dp[0]]);
s.sort()
// For the first k-sized window.
for (var i = 1; i < k; i++)
{
let l = s[0][0]
let min = s[0][1]
// Update log value by adding previous
// minimum log value
p[i] = Math.log(arr[i]) + l;
// Update dp[i]
dp[i] = (arr[i] * min) % mod;
// Insert it again into the multiset
// since it is within the k-size window
s.push([p[i], dp[i]]);
s.sort((a, b) => (a[0] != b[0]) ? (a[0] < b[0]) : (a[1] < b[1]))
}
for (var i = k; i < n; i++)
{
let l = s[0][0]
let min = s[0][1]
p[i] = Math.log(arr[i]) + l;
dp[i] = (arr[i] * min) % mod;
// Eliminate previous value which falls out
// of the k-sized window
if (s.indexOf([p[i - k], dp[i - k]] != -1))
s.splice(s.indexOf([p[i - k], dp[i - k]]), 1)
// Insert newest value to enter in
// the k-sized window.
s.push([p[i], dp[i]]);
s.sort((a, b) => (a[0] != b[0]) ? (a[0] > b[0]) : (a[1] > b[1]))
}
// dp[n - 1] will have minimum product %
// mod such that adjacent elements are
// separated by a max distance K
return dp[n - 1];
}
// Driver Code
let arr = [ 1, 2, 3, 4 ]
let n = arr.length
let k = 2;
console.log(minimumProductSubsequence(arr, n, k))
// This code is contributed by phasing17
Time Complexity: O(N* log(N))
Auxiliary Space: O(N), since N extra space has been taken.
Similar Reads
Product of all Subsequences of size K except the minimum and maximum Elements Given an array A[] containing N elements and an integer K. The task is to calculate the product of all elements of subsequences of size K except the minimum and the maximum elements for each subsequence. Note: Since the answer can be very large so print the final answer as mod of 109 + 7. Examples:
12 min read
Product of all Subsequences of size K except the minimum and maximum Elements Given an array A[] containing N elements and an integer K. The task is to calculate the product of all elements of subsequences of size K except the minimum and the maximum elements for each subsequence. Note: Since the answer can be very large so print the final answer as mod of 109 + 7. Examples:
12 min read
Product of all Subsequences of size K except the minimum and maximum Elements Given an array A[] containing N elements and an integer K. The task is to calculate the product of all elements of subsequences of size K except the minimum and the maximum elements for each subsequence. Note: Since the answer can be very large so print the final answer as mod of 109 + 7. Examples:
12 min read
Minimum number of distinct elements present in a K-length subsequence in an array Given an array A[] consisting of N integers and an integer K, the task is to count the minimum number of distinct elements present in a subsequence of length K of the given array, A. Examples: Input: A = {3, 1, 3, 2, 3, 4, 5, 4}, K = 4Output: 2Explanation: The subsequence of length 4 containing mini
7 min read
Maximum subsequence sum such that all elements are K distance apart Given an array arr[] of N integers and another integer K. The task is to find the maximum sum of a subsequence such that the difference of the indices of all consecutive elements in the subsequence in the original array is exactly K. For example, if arr[i] is the first element of the subsequence the
10 min read
Maximum subsequence sum such that all elements are K distance apart Given an array arr[] of N integers and another integer K. The task is to find the maximum sum of a subsequence such that the difference of the indices of all consecutive elements in the subsequence in the original array is exactly K. For example, if arr[i] is the first element of the subsequence the
10 min read