📌  相关文章
📜  连续元素绝对差之和最大的最小子序列

📅  最后修改于: 2021-10-26 05:13:32             🧑  作者: Mango

给定一个长度为N的数组arr[] ,包含范围[1, N] 中的值,任务是找到一个子序列s 1 , s 2 , …, s k使得
\\ Sum = \mid s1 - s2 \mid + \mid s2 - s3 \mid + ... + \mid s_{k-1} - s_{k} \mid
最大化。如果多个子序列具有最大可能的总和,则打印最小的一个。

天真的方法:
生成所有长度 >= 2 的子序列并计算它们各自的总和。跟踪为任何子序列获得的最大和。在多个子序列具有最大和的情况下,不断更新最小长度,并保持该子序列。最后打印子序列。
时间复杂度: O(2 N )
有效的方法:
有一些关键的观察可以帮助我们继续进行:

  1. 当考虑排列中的所有元素时,将获得最大和。
    例如:
  1. 现在我们知道最大可能的总和,目标是在不影响这个最大总和的情况下最小化子序列长度。
  2. 对于单调递增或递减的子序列,只考虑第一个和最后一个元素就可以达到最大和,例如:

这样可以在不影响Max sum 的情况下减少子序列的长度。
因此,从给定的数组中,不断提取单调递增或递减子序列的端点,并按以下方式将它们添加到子序列中:

  • 排列的第一个最后一个元素是默认端点
  • 如果P[ i – 1 ] < P[ i ] > P[ i + 1 ],则元素P[ i ]单调递增的端点
  • 如果P[ i – 1 ] > P[ i ] < P[ i + 1 ],则元素P[ i ]单调递减的端点

如此获得的子序列将具有最大和和最小长度。
下面是上述方法的实现:

C++
// C++ program to find
// smallest subsequence
// with sum of absolute
// difference of consecutive
// elements maximized
#include 
using namespace std;
 
// Function to print the smallest
// subsequence and its sum
void getSubsequence(vector& arr,
                    int n)
{
    // Final subsequence
    vector req;
 
    // First element is
    // a default endpoint
    req.push_back(arr[0]);
 
    // Iterating through the array
    for (int i = 1; i < n - 1; i++) {
 
        // Check for monotonically
        // increasing endpoint
        if (arr[i] > arr[i + 1]
            && arr[i] > arr[i - 1])
            req.push_back(arr[i]);
 
        // Check for monotonically
        // decreasing endpoint
        else if (arr[i] < arr[i + 1]
                 && arr[i] < arr[i - 1])
            req.push_back(arr[i]);
    }
 
    // Last element is
    // a default endpoint
    req.push_back(arr[n - 1]);
 
    // Length of final subsequence
    cout << req.size() << endl;
 
    // Print the subsequence
    for (auto x : req)
        cout << x << " ";
}
 
// Driver Program
int main()
{
    vector arr = { 1, 2, 5, 3,
                        6, 7, 4 };
    int n = arr.size();
    getSubsequence(arr, n);
 
    return 0;
}


Java
// Java program to find smallest
// subsequence with sum of absolute
// difference of consecutive
// elements maximized
import java.util.*;
 
class GFG{
 
// Function to print the smallest
// subsequence and its sum
static void getSubsequence(int []arr, int n)
{
     
    // Final subsequence
    Vector req = new Vector();
 
    // First element is
    // a default endpoint
    req.add(arr[0]);
 
    // Iterating through the array
    for(int i = 1; i < n - 1; i++)
    {
         
       // Check for monotonically
       // increasing endpoint
       if (arr[i] > arr[i + 1] &&
           arr[i] > arr[i - 1])
           req.add(arr[i]);
            
       // Check for monotonically
       // decreasing endpoint
       else if (arr[i] < arr[i + 1] &&
                arr[i] < arr[i - 1])
           req.add(arr[i]);
    }
 
    // Last element is
    // a default endpoint
    req.add(arr[n - 1]);
 
    // Length of final subsequence
    System.out.print(req.size() + "\n");
 
    // Print the subsequence
    for(int x : req)
       System.out.print(x + " ");
}
 
// Driver code
public static void main(String[] args)
{
    int []arr = { 1, 2, 5, 3,
                  6, 7, 4 };
    int n = arr.length;
     
    getSubsequence(arr, n);
}
}
 
// This code is contributed by Amit Katiyar


Python3
# Python3 program to find smallest
# subsequence with sum of absolute
# difference of consecutive
# elements maximized
 
# Function to print the smallest
# subsequence and its sum
def getSubsequence(arr, n):
     
    # Final subsequence
    req = []
     
    # First element is
    # a default endpoint
    req.append(arr[0])
     
    # Iterating through the array
    for i in range(1, n - 1):
         
        # Check for monotonically
        # increasing endpoint
        if (arr[i] > arr[i + 1] and
            arr[i] > arr[i - 1]):
            req.append(arr[i])
        
        # Check for monotonically
        # decreasing endpoint
        elif (arr[i] < arr[i + 1] and
              arr[i] < arr[i - 1]):
            req.append(arr[i]);
             
    # Last element is
    # a default endpoint
    req.append(arr[n - 1]);
 
    # Length of final subsequence
    print(len(req))
 
    # Print the subsequence
    for x in req:
        print(x, end = ' ')
 
# Driver code
if __name__=='__main__':
     
    arr = [ 1, 2, 5, 3, 6, 7, 4 ]
    n = len(arr)
     
    getSubsequence(arr, n)
 
# This code is contributed by rutvik_56


C#
// C# program to find smallest
// subsequence with sum of absolute
// difference of consecutive
// elements maximized
using System;
using System.Collections.Generic;
 
class GFG{
  
// Function to print the smallest
// subsequence and its sum
static void getSubsequence(int []arr, int n)
{
      
    // Final subsequence
    List req = new List();
  
    // First element is
    // a default endpoint
    req.Add(arr[0]);
  
    // Iterating through the array
    for(int i = 1; i < n - 1; i++)
    {
          
       // Check for monotonically
       // increasing endpoint
       if (arr[i] > arr[i + 1] &&
           arr[i] > arr[i - 1])
           req.Add(arr[i]);
             
       // Check for monotonically
       // decreasing endpoint
       else if (arr[i] < arr[i + 1] &&
                arr[i] < arr[i - 1])
           req.Add(arr[i]);
    }
  
    // Last element is
    // a default endpoint
    req.Add(arr[n - 1]);
  
    // Length of readonly subsequence
    Console.Write(req.Count + "\n");
  
    // Print the subsequence
    foreach(int x in req)
       Console.Write(x + " ");
}
  
// Driver code
public static void Main(String[] args)
{
    int []arr = { 1, 2, 5, 3,
                  6, 7, 4 };
    int n = arr.Length;
      
    getSubsequence(arr, n);
}
}
 
// This code is contributed by Amit Katiyar


输出:
5
1 5 3 7 4

时间复杂度: O(N)