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

📅  最后修改于: 2021-09-17 07:46:33             🧑  作者: Mango

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

例子:

朴素的方法:朴素的方法是生成数组的所有子序列并保持相邻元素之间的索引差异并找到最小乘积子序列。
有效的方法:一种有效的方法是使用动态规划。让dp[i]表示直到索引 ‘i’的元素的最小乘积,包括 arr[i] ,它们被最大距离K分开。那么 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)

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程