Problem: HJ24 合唱队
题目描述
描述
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位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。
数据范围:
输入描述:
用例两行数据,第一行是同学的总数 N ,第二行是 N 位同学的身高,以空格隔开
输出描述:
最少需要几位同学出列
示例1
输入:
8 186 186 150 200 160 130 197 200
输出:4
算法流程
- 初始化两个数组
increasing和decreasing,长度都为N,并将所有元素初始化为1。- 从左到右遍历数组,计算
increasing[i]的值。对于每个位置i,我们需要找到在i之前的所有位置j,使得height[j] < height[i],并且increasing[j] + 1 > increasing[i],则更新increasing[i] = increasing[j] + 1。- 从右到左遍历数组,计算
decreasing[i]的值。对于每个位置i,我们需要找到在i之后的所有位置j,使得height[j] < height[i],并且decreasing[j] + 1 > decreasing[i],则更新decreasing[i] = decreasing[j] + 1。- 遍历数组,找到最大的
increasing[i] + decreasing[i] - 1,即为最长的合唱队形的长度。- 最少需要出列的同学数目为N减去最长的合唱队形的长度。
代码
function minimumStudentsOut(heights) {
const N = heights.length;
const increasing = new Array(N).fill(1);
const decreasing = new Array(N).fill(1);
// 计算increasing数组
for (let i = 1; i < N; i++) {
for (let j = 0; j < i; j++) {
if (heights[j] < heights[i] && increasing[j] + 1 > increasing[i]) {
increasing[i] = increasing[j] + 1;
}
}
}
// 计算decreasing数组
for (let i = N - 2; i >= 0; i--) {
for (let j = N - 1; j > i; j--) {
if (heights[j] < heights[i] && decreasing[j] + 1 > decreasing[i]) {
decreasing[i] = decreasing[j] + 1;
}
}
}
let maxLength = 0;
for (let i = 0; i < N; i++) {
const length = increasing[i] + decreasing[i] - 1;
if (length > maxLength) {
maxLength = length;
}
}
const minimumOut = N - maxLength;
return minimumOut;
}
复杂度
-
时间复杂度:
-
空间复杂度: