合唱队-最长子序列

题目描述

计算最少出列多少位同学,使得剩下的同学排成合唱队形

设K位同学从左到右依次编号为1,2…,K,他们的身高分别为T1,T2,…,TK,   则他们的身高满足存在i(1<=i<=K)使得T1<T2<......<Ti-1<Ti>Ti+1>......>TK。

所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。

注意不许改变队列元素的先后顺序

请注意处理多组输入输出!

 

最长子序列问题

先找到每一个位置i左侧的最长上升子序列长度numL[i]:每一个位置左侧最长子序列长度等于其左侧比它小的所有位置的最长子序列长度中的最大值+1
再找到每一个位置i右侧的最长下降子序列长度numR[i]:每一个位置右侧最长子序列长度等于其右侧比它小的所有位置的最长子序列长度中的最大值+1
然后求出所有位置的最长序列长度=左侧最长子序列长度+右侧最长子序列长度-1(因为该位置被算了两次,所以减1)
然后用数目减去最长序列长度就是答案(牛客大神原话)

 

import java.io.*;

public class Main {
    public static void main(String[] args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String in = "";
 
		while ((in = br.readLine()) != null && !"".equals(in)) {
			int perCount = Integer.parseInt(in);
            
            in = br.readLine();
            String[] temp = in.split(" ");

            // 转成int
            int[] intArr = new int[temp.length];
            for(int i = 0; i < temp.length; i++) {
                intArr[i] = Integer.parseInt(temp[i]);
            }
            
            System.out.println(calc(intArr));
        }
    }
    
    public static int calc(int[] arr) {
        int[] numL = new int[arr.length];
        int[] numR = new int[arr.length];
        
        for(int i = 0; i < numL.length; i++) {
            for(int j = 0; j < i; j++) {
                if (arr[j] < arr[i]) {
                    numL[i] = Math.max(numL[j], numL[i]);
                }
            }
            numL[i] += 1;
        }
        
    //    printArr(numL);
         for(int i = arr.length - 1; i >= 0; i--) {
            for(int j = arr.length - 1; j > i; j--) {
                if (arr[i] > arr[j]) {
                    numR[i] = Math.max(numR[j], numR[i]);
                }
            }
            numR[i] += 1;
        }
    //    printArr(numR);
        int max = 0;
        for(int i = 0; i < arr.length; i++) {
            max = Math.max(max, numL[i] + numR[i] - 1);
        }
        
        return arr.length - max;
    }
    
    public static void printArr(int[] a) {
        for(int i = 0; i< a.length; i++) {
            System.out.print(" " + a[i]);
        }
        System.out.println();
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值