📌  相关文章
📜  不属于数组中增加或减少子序列的元素的最小数量

📅  最后修改于: 2021-04-26 08:16:10             🧑  作者: Mango

给定n个元素的数组。从数组中严格增加和严格减少子序列,以使每个数组元素都属于递增子序列或递减子序列,但不能同时属于这两个子元素,也可以不属于任何子序列。尽量减少不属于任何子序列的元素的数量,并找到这些元素的数量。

例子:

Input : arr[] = { 7, 8, 1, 2, 4, 6, 3, 5, 2, 1, 8, 7 }
Output : 2
Increasing sequence can be { 1, 2, 4, 5, 8 }.
Decreasing sequence can be { 7, 6, 3, 2, 1 }.
So, only 2 (8, 7) element is left which are not part of
either of the subsequences.

Input : arr[] = { 1, 4, 2, 3, 3, 2, 4, 1 }
Output : 0
Increasing sequence can be { 1, 2, 3, 4 }.
Decreasing sequence can be { 4, 3, 2, 1 }.
So, no element is left which is not part of either of 
the subsequences.

这个想法是从索引0开始,对每个索引一个接一个地做出决定。对于每个索引,可能存在三种可能性,第一,它可以属于递增序列,第二,它可以属于递减序列,第三,它不属于任何这些序列。
因此,对于每个索引,通过将其视为递增子序列的一部分或递减子序列的一部分,来检查最佳答案(不是任何子序列的一部分的最小元素)。如果他们无法获得最佳答案,则将其保留为不属于任何序列的元素。

为了降低复杂度(使用动态编程),我们可以使用3D数组dp [x] [y] [z]存储不属于任何子序列的元素的数量,其中x表示决策索引,y表示决策索引递减序列的最后一个索引,z表示递减序列的最后一个索引。

以下是此方法的实现:

C++
// C++ program to return minimum number of elements which
// are not part of increasing or decreasing subsequences.
#include
#define MAX 102
using namespace std;
  
// Return minimum number of elements which is not part of
// any of the sequence.
int countMin(int arr[], int dp[MAX][MAX][MAX], int n, int dec,
                                            int inc, int i)
{
    // If already calculated, return value.
    if (dp[dec][inc][i] != -1)
        return dp[dec][inc][i];
  
    // If whole array is traversed.
    if (i == n)
        return 0;
  
    // calculating by considering element as part of
    // decreasing sequence.
    if (arr[i] < arr[dec])
        dp[dec][inc][i] = countMin(arr, dp, n, i, inc, i + 1);
  
    // calculating by considering element as part of
    // increasing sequence.
    if (arr[i] > arr[inc])
    {
        // If cannot be calculated for decreasing sequence.
        if (dp[dec][inc][i] == -1)
            dp[dec][inc][i] = countMin(arr, dp, n, dec, i, i + 1);
  
        // After considering once by decreasing sequence, now try
        // for increasing sequence.
        else
            dp[dec][inc][i] = min(countMin(arr, dp, n, dec, i, i + 1),
                                                  dp[dec][inc][i]);
    }
  
    // If element cannot be part of any of the sequence.
    if (dp[dec][inc][i] == -1)
        dp[dec][inc][i] = 1 + countMin(arr, dp, n, dec, inc, i + 1);
  
    // After considering element as part of increasing and
    // decreasing sequence trying as not part of any of the
    // sequence.
    else
        dp[dec][inc][i] = min(1 + countMin(arr, dp, n, dec, inc, i + 1),
                                                    dp[dec][inc][i]);
  
    return dp[dec][inc][i];
}
  
// Wrapper Function
int wrapper(int arr[], int n)
{
    // Adding two number at the end of array, so that
    // increasing and decreasing sequence can be made.
    // MAX - 2 index is assigned INT_MAX for decreasing sequence
    // because/ next number of sequence must be less than it.
    // Similarly, for Increasing sequence INT_MIN is assigned to
    // MAX - 1 index.
    arr[MAX - 2] = INT_MAX;
    arr[MAX - 1] = INT_MIN;
  
    int dp[MAX][MAX][MAX];
    memset(dp, -1, sizeof dp);
  
    return countMin(arr, dp, n, MAX - 2, MAX - 1, 0);
}
  
// Driven Program
int main()
{
    int n = 12;
    int arr[MAX] = { 7, 8, 1, 2, 4, 6, 3, 5, 2, 1, 8, 7 };
  
    cout << wrapper(arr, n) << endl;
    return 0;
}


Java
// Java program to return minimum number of 
// elements which are not part of increasing
// or decreasing subsequences.
import java.util.*;
  
class GFG
{
  
static int MAX = 102;
  
// Return minimum number of elements which is 
// not part of any of the sequence.
static int countMin(int arr[], int dp[][][], int n,
                    int dec, int inc, int i)
{
    // If already calculated, return value.
    if (dp[dec][inc][i] != -1)
        return dp[dec][inc][i];
  
    // If whole array is traversed.
    if (i == n)
        return 0;
  
    // calculating by considering element as 
    // part of decreasing sequence.
    if (arr[i] < arr[dec])
        dp[dec][inc][i] = countMin(arr, dp, n, i, 
                                     inc, i + 1);
  
    // calculating by considering element as 
    // part of increasing sequence.
    if (arr[i] > arr[inc])
    {
        // If cannot be calculated for 
        // decreasing sequence.
        if (dp[dec][inc][i] == -1)
            dp[dec][inc][i] = countMin(arr, dp, n,
                                       dec, i, i + 1);
  
        // After considering once by decreasing sequence, 
        // now try for increasing sequence.
        else
            dp[dec][inc][i] = Math.min(countMin(arr, dp, n,
                                                dec, i, i + 1),
                                                dp[dec][inc][i]);
    }
  
    // If element cannot be part of any of the sequence.
    if (dp[dec][inc][i] == -1)
        dp[dec][inc][i] = 1 + countMin(arr, dp, n, 
                                       dec, inc, i + 1);
  
    // After considering element as part of increasing and
    // decreasing sequence trying as not part of any of the
    // sequence.
    else
        dp[dec][inc][i] = Math.min(1 + countMin(arr, dp, n,     
                                                dec, inc, i + 1),
                                                dp[dec][inc][i]);
  
    return dp[dec][inc][i];
}
  
// Wrapper Function
static int wrapper(int arr[], int n)
{
    // Adding two number at the end of array, 
    // so that increasing and decreasing sequence 
    // can be made. MAX - 2 index is assigned 
    // INT_MAX for decreasing sequence because
    // next number of sequence must be less than it.
    // Similarly, for Increasing sequence INT_MIN 
    // is assigned to MAX - 1 index.
    arr[MAX - 2] = Integer.MAX_VALUE;
    arr[MAX - 1] = Integer.MIN_VALUE;
  
    int [][][]dp = new int[MAX][MAX][MAX];
    for(int i = 0; i < MAX; i++)
    {
        for(int j = 0; j < MAX; j++)
        {
            for(int l = 0; l < MAX; l++)
            dp[i][j][l] = -1;
        }
    }
  
    return countMin(arr, dp, n, MAX - 2, 
                                MAX - 1, 0);
}
  
// Driver Code
public static void main(String[] args) 
{
    int n = 12; 
    int[] arr = new int[MAX];
    arr[0] = 7;
    arr[1] = 8;
    arr[2] = 1;
    arr[3] = 2;
    arr[4] = 4;
    arr[5] = 6;
    arr[6] = 3;
    arr[7] = 5;
    arr[8] = 2;
    arr[9] = 1;
    arr[10] = 8;
    arr[11] = 7; 
  
    System.out.println(wrapper(arr, n));
}
} 
  
// This code is contributed by 29AjayKumar


Python3
# Python3 program to return minimum number of elements which 
# are not part of increasing or decreasing subsequences. 
MAX=102
  
# Return minimum number of elements which is not part of 
# any of the sequence. 
  
def countMin(arr,dp,n,dec,inc,i):
      
    # If already calculated, return value.
    if dp[dec][inc][i] != -1:
        return dp[dec][inc][i]
          
    # If whole array is traversed. 
    if i==n:
        return 0
          
    # calculating by considering element as part of 
    # decreasing sequence. 
    if arr[i] arr[inc]:
          
        # If cannot be calculated for 
        # decreasing sequence.
        if dp[dec][inc][i] == -1:
            dp[dec][inc][i] = countMin(arr, dp, n, dec, i, i + 1)
              
        # After considering once by 
        # decreasing sequence, now try
        # for increasing sequence. 
        else:
            dp[dec][inc][i] = min(countMin(arr,dp,n,dec,i,i+1),dp[dec][inc][i])
  
    # If element cannot be part 
    # of any of the sequence.
    if dp[dec][inc][i] == -1:
        dp[dec][inc][i] = 1 + countMin(arr, dp, n, dec, inc, i + 1)
  
    # After considering element as part of increasing and 
    # decreasing sequence trying as not part of any of the
    # sequence. 
    else:
        dp[dec][inc][i]=min(1+countMin(arr,dp,n,dec,inc,i+1),dp[dec][inc][i])
  
    return dp[dec][inc][i]
  
# Wrapper Function
def wrapper(arr,n) :
  
    # Adding two number at the end of array, so that 
    # increasing and decreasing sequence can be made.
    # MAX - 2 index is assigned INT_MAX for decreasing sequence 
    # because/ next number of sequence must be less than it. 
    # Similarly, for Increasing sequence INT_MIN is assigned to 
    # MAX - 1 index.
    arr[MAX-2]=1000000000
    arr[MAX-1]=-1000000000
    dp=[[[-1 for i in range(MAX)] for i in range(MAX)] for i in range(MAX)]
    return countMin(arr,dp,n,MAX-2,MAX-1,0)
      
# Driver code
if __name__=='__main__':
    n=12
    arr=[ 7, 8, 1, 2, 4, 6, 3, 5, 2, 1, 8, 7]
    for i in range(MAX):
        arr.append(0)
    print(wrapper(arr,n))
      
# This code is contributed by sahilshelangia


C#
// C# program to return minimum number of
// elements which are not part of increasing
// or decreasing subsequences. 
using System; 
  
class GFG 
{ 
static int MAX = 102; 
  
// Return minimum number of elements 
// which is not part of any of the sequence. 
static int countMin(int[] arr, int[,,] dp, int n,   
                    int dec, int inc, int i) 
{ 
    // If already calculated, return value. 
    if (dp[dec, inc, i] != -1) 
        return dp[dec, inc, i]; 
   
    // If whole array is traversed. 
    if (i == n) 
        return 0; 
  
    // calculating by considering element 
    // as part of decreasing sequence. 
    if (arr[i] < arr[dec]) 
        dp[dec, inc, i] = countMin(arr, dp, n, i,
                                        inc, i + 1); 
  
    // calculating by considering element 
    // as part of increasing sequence. 
    if (arr[i] > arr[inc]) 
    { 
        // If cannot be calculated for 
        // decreasing sequence. 
        if (dp[dec, inc, i] == -1) 
            dp[dec, inc, i] = countMin(arr, dp, n,
                                       dec, i, i + 1); 
  
        // After considering once by decreasing 
        // sequence, now try for increasing sequence. 
        else
            dp[dec, inc, i] = Math.Min(countMin(arr, dp, n, 
                                                dec, i, i + 1), 
                                                dp[dec, inc, i]); 
    } 
  
    // If element cannot be part of any of the sequence. 
    if (dp[dec, inc, i] == -1) 
        dp[dec, inc, i] = 1 + countMin(arr, dp, n, dec, 
                                            inc, i + 1); 
  
    // After considering element as part of 
    // increasing and decreasing sequence
    // trying as not part of any of the 
    // sequence. 
    else
        dp[dec, inc, i] = Math.Min(1 + countMin(arr, dp, n, 
                                                dec, inc, i + 1), 
                                                dp[dec, inc, i]); 
  
    return dp[dec, inc, i]; 
} 
  
// Wrapper Function 
static int wrapper(int[] arr, int n) 
{ 
    // Adding two number at the end of array, 
    // so that increasing and decreasing sequence 
    // can be made. MAX - 2 index is assigned
    // INT_MAX for decreasing sequence because next 
    // number of sequence must be less than it. 
    // Similarly, for Increasing sequence INT_MIN 
    // is assigned to MAX - 1 index. 
    arr[MAX - 2] = int.MaxValue; 
    arr[MAX - 1] = int.MinValue; 
  
    int[,,] dp = new int[MAX, MAX, MAX]; 
    for(int i = 0; i < MAX; i++)
        for(int j = 0; j < MAX; j++)
            for(int k = 0; k < MAX; k++)
                dp[i, j, k] = -1;
  
    return countMin(arr, dp, n, MAX - 2, 
                                MAX - 1, 0); 
} 
  
// Driver Code
static void Main() 
{ 
    int n = 12; 
    int[] arr = new int[MAX];
    arr[0] = 7;
    arr[1] = 8;
    arr[2] = 1;
    arr[3] = 2;
    arr[4] = 4;
    arr[5] = 6;
    arr[6] = 3;
    arr[7] = 5;
    arr[8] = 2;
    arr[9] = 1;
    arr[10] = 8;
    arr[11] = 7; 
  
    Console.Write(wrapper(arr, n));
}
}
  
// This code is contributed by DrRoot_


输出:

2

时间复杂度: O(n 3 )