📜  至少有k个距离元素的最大和子序列

📅  最后修改于: 2021-04-24 14:37:04             🧑  作者: Mango

给定一个数组和一个数字k,找到一个子序列,使得

  1. 子序列中的元素总数最大
  2. 子序列元素的索引至少相差k

      例子

      Input : arr[] = {4, 5, 8, 7, 5, 4, 3, 4, 6, 5}
                 k = 2
      Output: 19
      Explanation: The highest value is obtained 
      if you pick indices 1, 4, 7, 10 giving 
      4 + 7 + 3 + 5 = 19
      
      Input: arr[] = {50, 70, 40, 50, 90, 70, 60, 
                                    40, 70, 50}
                 k = 2
      Output: 230
      Explanation: There are 10 elements and k = 2. 
      If you select 2, 5, and 9 you get a total 
      value of 230, which is the maximum possible.
      

      一个简单的解决方案是一一考虑所有子序列。在每个子序列中,检查距离条件并返回最大总和子序列。

      一个有效的解决方案是使用动态编程。

      有两种情况:

      1. 如果我们选择索引i处的元素,使得i + k + 1> = N,那么我们就不能选择任何其他元素作为子序列的一部分。因此,我们需要决定是选择该元素还是选择其后的元素之一。
      2. 如果我们在索引i处选择元素,使i + k + 1

      这两种情况可以写成:

      Let MS[i] denotes the maximum sum of subsequence 
      from i = N-2 to 0. 
      
      Base Case: 
         MS[N-1] = arr[N-1]
      
      If  i + 1 + k >= N
         MS[i] = max(arr[i], MS[i+1]),  
      Else
         MS[i] = max(arr[i] + MS[i+k+1], MS[i+1])
      
      Evidently, the solution to the problem
      is to find MS[0].

      下面是实现:

      C++
      // CPP program to find maximum sum subsequence
      // such that elements are at least k distance
      // away.
      #include 
      using namespace std;
        
      int maxSum(int arr[], int N, int k)
      {
          // MS[i] is going to store maximum sum
          // subsequence in subarray from arr[i]
          // to arr[n-1]
          int MS[N];
        
          // We fill MS from right to left.
          MS[N - 1] = arr[N - 1];
          for (int i = N - 2; i >= 0; i--) {
              if (i + k + 1 >= N)
                  MS[i] = max(arr[i], MS[i + 1]);
              else
                  MS[i] = max(arr[i] + MS[i + k + 1], MS[i + 1]);
          }
        
          return MS[0];
      }
        
      // Driver code
      int main()
      {
          int N = 10, k = 2;
          int arr[] = { 50, 70, 40, 50, 90, 70, 60, 40, 70, 50 };
          cout << maxSum(arr, N, k);
          return 0;
      }


      Java
      // Java program to find maximum sum subsequence
      // such that elements are at least k distance
      // away.
      import java.io.*;
        
      class GFG {
        
          static int maxSum(int arr[], int N, int k)
          {
              // MS[i] is going to store maximum sum
              // subsequence in subarray from arr[i]
              // to arr[n-1]
              int MS[] = new int[N];
        
              // We fill MS from right to left.
              MS[N - 1] = arr[N - 1];
              for (int i = N - 2; i >= 0; i--) {
                  if (i + k + 1 >= N)
                      MS[i] = Math.max(arr[i], MS[i + 1]);
                  else
                      MS[i] = Math.max(arr[i] + MS[i + k + 1],
                                      MS[i + 1]);
              }
        
              return MS[0];
          }
        
          // Driver code
          public static void main(String[] args)
          {
              int N = 10, k = 2;
              int arr[] = { 50, 70, 40, 50, 90, 70, 60,
                            40, 70, 50 };
              System.out.println(maxSum(arr, N, k));
          }
      }
      // This code is contributed by Prerna Saini


      Python3
      # Python3 program to find maximum
      # sum subsequence such that elements
      # are at least k distance away.
        
      def maxSum(arr, N, k):
        
          # MS[i] is going to store maximum sum
          # subsequence in subarray from arr[i]
          # to arr[n-1]
          MS = [0 for i in range(N)]
        
          # We fill MS from right to left.
          MS[N - 1] = arr[N - 1]
          for i in range(N - 2, -1, -1):
              if (i + k + 1 >= N):
                  MS[i] = max(arr[i], MS[i + 1])
              else:
                  MS[i] = max(arr[i] + MS[i + k + 1],
                                       MS[i + 1])
            
          return MS[0]
        
      # Driver code
      N = 10; k = 2
      arr = [ 50, 70, 40, 50, 90, 70, 60, 40, 70, 50 ]
      print(maxSum(arr, N, k))
            
      # This code is contributed by Anant Agarwal.


      C#
      // C# program to find maximum sum
      // subsequence such that elements
      // are at least k distance away.
      using System;
         
      class GFG {
         
          static int maxSum(int []arr, int N, int k)
          {
              // MS[i] is going to store maximum sum
              // subsequence in subarray from arr[i]
              // to arr[n-1]
              int []MS = new int[N];
         
              // We fill MS from right to left.
              MS[N - 1] = arr[N - 1];
              for (int i = N - 2; i >= 0; i--) {
                    
                  if (i + k + 1 >= N)
                      MS[i] = Math.Max(arr[i], MS[i + 1]);
                  else
                      MS[i] = Math.Max(arr[i] + MS[i + k + 1],
                                      MS[i + 1]);
              }
         
              return MS[0];
          }
         
          // Driver code
          public static void Main()
          {
              int N = 10, k = 2;
              int []arr = { 50, 70, 40, 50, 90, 70, 60,
                                          40, 70, 50 };
              Console.WriteLine(maxSum(arr, N, k));
          }
      }
        
      // This code is contributed by Anant Agarwal.


      PHP
      = 0; $i--) 
          {
              if ($i + $k + 1 >= $N)
                  $MS[$i] = max($arr[$i], 
                            $MS[$i + 1]);
              else
                  $MS[$i] = max($arr[$i] + 
                            $MS[$i + $k + 1], 
                            $MS[$i + 1]);
          }
        
          return $MS[0];
      }
        
      // Driver code
      $N = 10; $k = 2;
      $arr = array(50, 70, 40, 50, 90, 
                   70, 60, 40, 70, 50);
      echo(maxSum($arr, $N, $k));
        
      // This code is contributed by Ajit.
      ?>


      输出:

      230
      

      时间复杂度:O(n)
      辅助空间:O(n)