给定数组arr []和整数K ,任务是找出子序列的最小乘积,其中子序列的相邻元素之间的最大距离为K。
注意:子序列应包括数组的第一个和最后一个元素。
例子:
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
天真的方法:天真的方法是生成数组的所有子序列,并在相邻元素之间保持索引差,并找到最小乘积子序列。
高效的方法:一种有效的方法是使用动态编程。令dp [i]表示直到索引’i’的元素的最小乘积,其中包括由最大距离K隔开的arr [i] 。然后,可以将dp [i]公式如下:
dp[i] = arr[i] * min{dp[j]} where j < i and 1 <= i - j <= K.
为了计算dp [i] ,可以维护并遍历大小为K的窗口以找到dp [j]的最小值,然后可以将其乘以arr [i] 。但是,这将导致O(N * K)解决方案。
为了进一步优化解决方案,可以将产品的值存储在STL集中,然后可以在O(log n)时间中找到产品的最小值。由于存储产品可能很麻烦,因为产品很容易超过10 18 ,因此我们将存储产品的对数值,因为log是单调函数,因此最小化对数值会自动意味着产品最小。
下面是上述方法的实现:
CPP
// C++ implementation of the above approach.
#include
#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 > 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 >::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;
}
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
8
时间复杂度: O(N * log(N))
辅助空间: O(N)