合唱队形

Posted debugxw

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了合唱队形相关的知识,希望对你有一定的参考价值。

题目

合唱队有 N 个人,编号为 0 到 N - 1,Height[i] 代表第 i 个人的身高,所有人站成一排。

现要将这 N 个人分为若干组,每一组的人员编号连续,且组内人员可以任意交换位置。

使得这 N 个人的身高从左往右为一个非递减数列。问最多可将其分为多少组?

输入描述

输入一个正整数 N 代表合唱队人数,接下来一行输入 N 个数代表每个人的身高

输出描述

输出一个数代表最多可将其分为多少组

样例输入

4
2 1 3 2

样例输出

2

说明

分为两组 [2, 1] [3, 2],组内交换顺序即可得到 [1, 2], [2, 3]

AC 代码

import java.util.Scanner;

/**
 * 关键思路:
 * 找到某个元素左边的最大值和右边的最小值
 * 如果leftMax[i] <= rightMin[i+1],则可以从i的右边界直接分开
 * <p>
 * 使用两个辅助数组:
 * leftMax[]:记录当前元素左边的最大值(包括当前值)
 * rightMin[]:记录当前元素右边的最小值(包括当前值)
 */
public class Main 

    public static void main(String[] args) 
        Scanner scanner = new Scanner(System.in);
        int N = scanner.nextInt();
        // 特殊情况
        if (N == 0 || N == 1)
            System.out.println(N);
        // 获取身高
        int[] height = new int[N];
        for (int i = 0; i < N; i++)
            height[i] = scanner.nextInt();

        int[] leftMax = new int[N];
        int[] rightMin = new int[N];
        leftMax[0] = height[0];
        rightMin[N - 1] = height[N - 1];
        for (int i = 1; i < N; i++) 
            leftMax[i] = Math.max(leftMax[i - 1], height[i]);
        
        for (int i = N - 2; i >= 0; i--) 
            rightMin[i] = Math.min(rightMin[i + 1], height[i]);
        
        int res = 1;
        for (int i = 0; i < N - 1; i++) 
            if (leftMax[i] <= rightMin[i + 1]) 
                res++;
            
        
        System.out.println(res);
    

以上是关于合唱队形的主要内容,如果未能解决你的问题,请参考以下文章

九度1131:合唱队形

动规——合唱队形

dp合唱队形

例9.8合唱队形

题目1131:合唱队形

合唱队形