给定一个长度为N的数组arr[] ,包含范围[1, N] 中的值,任务是找到一个子序列s 1 , s 2 , …, s k使得
被最大化。如果多个子序列具有最大可能的总和,则打印最小的一个。
Input: N = 3, P = {3, 2, 1}
Output: K = 2, S = {3, 1}
Explanation:
Maximum sum possible = 2
Subsequences {3, 2, 1} and {3, 1} achieves that sum.
Hence, the subsequence {3, 1} is considered being of smaller length.
Input: N = 4, P = {1, 3, 4, 2}
Output: K = 3, S = {1, 4, 2}
Explanation:
Maximum sum possible = 5
Subsequences {1, 3, 4, 2} and {1, 4, 2} achieves that sum.
Hence, the subsequence {1, 4, 2} is considered being of smaller length.
天真的方法:
生成所有长度 >= 2 的子序列并计算它们各自的总和。跟踪为任何子序列获得的最大和。在多个子序列具有最大和的情况下,不断更新最小长度,并保持该子序列。最后打印子序列。
时间复杂度: O(2 N )
有效的方法:
有一些关键的观察可以帮助我们继续进行:
- 当考虑排列中的所有元素时,将获得最大和。
例如:
N = 4, P = [1, 3, 4, 2]
Max sum = | 1 – 3 | + | 3 – 4 | + | 4 – 2 | = 2 + 1 + 2 = 5
Here, the length is N and the required subsequence is permutation P itself.
- 现在我们知道最大可能的总和,目标是在不影响这个最大总和的情况下最小化子序列长度。
- 对于单调递增或递减的子序列,只考虑第一个和最后一个元素就可以达到最大和,例如:
S = [1, 3, 5, 7]
Max sum = | 1 – 3 | + | 3 – 5 | + | 5 – 7 | = 2 + 2 + 2 = 6, K = 4
Considering only first and last element,
S = [1, 7]
Max sum = | 1 – 7 | = 6, K = 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)