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

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

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程