算法:合唱队

描述

N 位同学站成一排,音乐老师要请最少的同学出列,使得剩下的 K 位同学排成合唱队形。

设K位同学从左到右依次编号为 1,2…,K ,他们的身高分别为T1​,T2​,…,TK​ ,若存在i(1≤i≤K) 使得T1​<T2​<......<Ti−1​<Ti​ 且 Ti​>Ti+1​>......>TK​,则称这K名同学排成了合唱队形。

通俗来说,能找到一个同学,他的两边的同学身高都依次严格降低的队形就是合唱队形。

例子:

123 124 125 123 121 是一个合唱队形

123 123 124 122不是合唱队形,因为前两名同学身高相等,不符合要求

123 122 121 122不是合唱队形,因为找不到一个同学,他的两侧同学身高递减。

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

注意:不允许改变队列元素的先后顺序  不要求最高同学左右人数必须相等

数据范围: 1≤�≤3000 1≤n≤3000 

输入描述:

用例两行数据,第一行是同学的总数 N ,第二行是 N 位同学的身高,以空格隔开

输出描述:

最少需要几位同学出列

示例1

输入:

8
186 186 150 200 160 130 197 200

输出:

4

说明:

由于不允许改变队列元素的先后顺序,所以最终剩下的队列应该为186 200 160 130或150 200 160 130           
import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int count = 0;
        int[] array = null;
        // 注意 hasNext 和 hasNextLine 的区别
        while (in.hasNextInt()) { // 注意 while 处理多个 case
            int a = in.nextInt();
            count = a;
            array = new int[a];
            for (int i=0; i<a; i++) {
                int tmp = in.nextInt();
                array[i] = tmp;
            }
        }

        
        System.out.println(count-getRes(array));
    }

    public static int getRes(int[] array) {
        int len = array.length;
        // 存放当前位置左边所有递增队列最大的数量
        int[] left = new int[len];
        // 存放当前位置右边所有递减队列最大的数量
        int[] right = new int[len];
        for (int i=0; i<len; i++) {
            if (i>0) {
                for (int j=i-1; j>=0; j--) {
                    if (array[i] > array[j]) {
                        left[i] = Math.max(left[j]+1, left[i]);
                    }
                }

                int r = len - 1 - i;
                for (int j=r+1; j<=len-1; j++) {
                    if (array[r] > array[j]) {
                        right[r] = Math.max(right[j]+1, right[r]);
                    }
                }
             }     
        }
        int max = 0;
        for (int i=0; i<len; i++) {
            max = Math.max(right[i]+left[i]+1, max);
        }
        return max;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值