📌  相关文章
📜  最多K个相邻元素的最大子序列和

📅  最后修改于: 2021-05-17 23:54:06             🧑  作者: Mango

给定一个由长度为N的整数和整数K (1 <= K <= N)组成的数组arr [] ,任务是找到数组中的最大子序列和,以使该子序列中的相邻元素具有在原始数组中,它们的索引最多相差K。换句话说,如果ij是原始数组中两个连续的子序列元素的索引,则| ij | <= K。

例子:

天真的方法:生成数组的所有可能子集,并检查每个子集是否满足条件,以使两个相邻元素的索引最多具有K的差。如果是,则将其总和与迄今为止获得的最大总和进行比较,如果该总和大于迄今为止获得的总和,则对其进行更新。

高效方法:可以使用动态编程解决此问题。

创建一个表dp [] ,其中dp [i]存储该子序列的最大和,直到第i索引为止。

  • 如果当前元素是子序列的第一个元素,则:
  • 否则,我们必须检查先前的结果,并在此索引后面的K窗口中检查dp的最大结果是什么:
  • 对于每个索引,请选择在该索引处给出最大总和的条件,因此最终的递归关系将是:

因此,为了检查K窗口中此索引后面的最大值是什么,我们可以从dp [i-1]迭代到dp [ik]并找到最大值,在这种情况下,时间复杂度将为O( N * K) ,也可以通过获取有序映射并保持每个索引的dp [i]值保持不变来减少它。这将复杂度降低到O(N * log(K))

下面是上述方法的实现。

C++
// C++ implementation to
// C++ program to
// find the maximum sum
// subsequence such that
// two adjacent element
// have atmost difference
// of K in their indices
 
#include 
#include 
#include 
using namespace std;
 
int max_sum(int arr[], int N,
            int K)
{
 
    // DP Array to store the
    // maximum sum obtained
    // till now
    int dp[N];
 
    // Ordered map to store DP
    // values in a window ok K
    map mp;
 
    // Initializing dp[0]=arr[0]
    dp[0] = arr[0];
 
    // Inserting value of DP[0]
    // in map
    mp[dp[0]]++;
 
    // Intializing final answer
    // with dp[0]
    int ans = dp[0];
 
    for (int i = 1;
         i < N; i++) {
 
        // when ifirst
                            + arr[i],
                        arr[i]);
 
            // Inserting dp value in map
            mp[dp[i]]++;
        }
        else {
 
            auto it = mp.end();
            it--;
            dp[i] = max(it->first
                            + arr[i],
                        arr[i]);
 
            mp[dp[i]]++;
 
            // Deleting dp[i-k] from
            // map beacuse window size
            // has become K+1
            mp[dp[i - K]]--;
 
            // Erase the key from if
            // count of dp[i-K] becomes
            // zero
            if (mp[dp[i - K]] == 0) {
 
                mp.erase(dp[i - K]);
            }
        }
 
        // Calculating final answer
        ans = max(ans, dp[i]);
    }
    return ans;
}
 
// Driver code
int main()
{
    int arr[] = { 1, 2, -2,
                  4, 3, 1 };
    int N = sizeof(arr) / sizeof(int);
    int K = 2;
    cout << max_sum(arr, N, K);
    return 0;
}


Java
// Java program to
// find the maximum sum
// subsequence such that
// two adjacent element
// have atmost difference
// of K in their indices
import java.util.*;
class GFG
{
  static int max_sum(int[] arr, int N, int K)
  {
 
    // DP Array to store the
    // maximum sum obtained
    // till now
    int[] dp = new int[N];
 
    // Ordered map to store DP
    // values in a window ok K
    HashMap mp = new HashMap<>();
 
    // Initializing dp[0]=arr[0]
    dp[0] = arr[0];
 
    // Inserting value of DP[0]
    // in map
    if(mp.containsKey(dp[0]))
    {
      mp.put(dp[0], mp.get(dp[0]) + 1);  
    }
    else{
      mp.put(dp[0], 1);
    }
 
    // Intializing final answer
    // with dp[0]
    int ans = dp[0];    
    for (int i = 1; i < N; i++)
    {
 
      // when i keySet = mp.keySet();
        ArrayList Keys = new ArrayList(keySet);
        dp[i] = Math.max(Keys.get(Keys.size()-1) + arr[i], arr[i]);
 
        // Inserting dp value in map
 
        if(mp.containsKey(dp[i]))
        {
          mp.put(dp[i], mp.get(dp[i]) + 1);
        }
        else{
          mp.put(dp[i], 1);
        }
      }
      else {
        Set keySet = mp.keySet();
        ArrayList Keys = new ArrayList(keySet);
        dp[i] = Math.max(Keys.get(Keys.size()-1) + arr[i], arr[i]);
 
        if(mp.containsKey(dp[i]))
        {
          mp.put(dp[i], mp.get(dp[i]) + 1);  
        }
        else{
          mp.put(dp[i], 1);
        }
 
        // Deleting dp[i-k] from
        // map beacuse window size
        // has become K+1
        if(mp.containsKey(dp[i - K]))
        {
          mp.put(dp[i - K], mp.get(dp[i - K]) - 1);
        }
        else{
          mp.put(dp[i - K], - 1);
        }
 
        // Erase the key from if
        // count of dp[i-K] becomes
        // zero
        if (mp.get(dp[i - K]) == 0)
        {  
          mp.remove(dp[i - K]);
        }
      }
 
      // Calculating final answer
      ans = Math.max(ans, dp[i]);
    }
    return ans;
  }
 
  // Driver code
  public static void main(String[] args) {
    int[] arr = { 1, 2, -2,
                 4, 3, 1 };
    int N = arr.length;
    int K = 2;
    System.out.println(max_sum(arr, N, K));
  }
}
 
// This code is contributed by divyesh072019


Python3
# Python3 program to
# find the maximum sum
# subsequence such that
# two adjacent element
# have atmost difference
# of K in their indices
 
def max_sum(arr, N, K):
  
    # DP Array to store the
    # maximum sum obtained
    # till now
    dp = [0 for i in range(N)]
  
    # Ordered map to store DP
    # values in a window ok K
    mp = dict()
  
    # Initializing dp[0]=arr[0]
    dp[0] = arr[0];
  
    # Inserting value of DP[0]
    # in map
    mp[dp[0]] = 1
  
    # Intializing final answer
    # with dp[0]
    ans = dp[0];
     
    for i in range(1, N):
  
        # when i


C#
// C# program to
// find the maximum sum
// subsequence such that
// two adjacent element
// have atmost difference
// of K in their indices
using System;
using System.Collections.Generic; 
using System.Linq;
class GFG
{
 
  static int max_sum(int[] arr, int N, int K)
  {
 
    // DP Array to store the
    // maximum sum obtained
    // till now
    int[] dp = new int[N];
 
    // Ordered map to store DP
    // values in a window ok K
    Dictionary mp = new Dictionary();
 
    // Initializing dp[0]=arr[0]
    dp[0] = arr[0];
 
    // Inserting value of DP[0]
    // in map
    if(mp.ContainsKey(dp[0]))
    {
      mp[dp[0]]++;  
    }
    else{
      mp[dp[0]] = 1;
    }
 
    // Intializing final answer
    // with dp[0]
    int ans = dp[0];    
    for (int i = 1; i < N; i++)
    {
 
      // when i


输出:
11

时间复杂度: O(N * log(K))