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

📅  最后修改于: 2021-09-17 16:09:34             🧑  作者: 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 because 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 because 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))