📌  相关文章
📜  最小乘积子序列,相邻元素之间的最大距离为K

📅  最后修改于: 2021-04-21 21:36:53             🧑  作者: Mango

给定数组arr []和整数K ,任务是找出子序列的最小乘积,其中子序列的相邻元素之间的最大距离为K。
注意:子序列应包括数组的第一个和最后一个元素。

例子:

天真的方法:天真的方法是生成数组的所有子序列,并在相邻元素之间保持索引差,并找到最小乘积子序列。
高效的方法:一种有效的方法是使用动态编程。令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)