描述
音乐课上,老师将 n 位同学排成一排。老师希望在不改变同学相对位置的前提下,从队伍中选出最少数量的同学,使得剩下的同学排成合唱队形。
记合唱队形中一共有 k 位同学,记编号为 1,2,…,k ,第 i 个人的身高为 hi 。要求:存在一位同学编号为 i(1<i<k) ,使得 h1,h2,…,hi−1 严格递增,且 hi+1,hi+2,…,hk 严格递减;更具体地,合唱队形呈 h1<h2<⋯<hi−1<hi 、hi>hi+1>⋯>hk 。
你能帮助老师计算,最少需要出列多少位同学,才能使得剩下的同学排成合唱队形?
输入描述:
第一行输入一个整数 n(1≦n≦3000) 代表同学数量。
第二行输入 n 个整数 h1,h2,…,hn(0≦hi≦105) 代表每一位同学的身高。
输出描述:
输出一个整数,代表最少需要出列的同学数量。
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;
void (async function () {
// Write your code here
const arr = [];
while ((line = await readline())) {
let tokens = line.split(" ");
arr.push(tokens);
}
let lineArr = arr[1].map(Number); //学生身高
const dpFn = (s) => { //构建一个动态规划一维数组函数
let dp = Array(s.length).fill(1); //将每一项作为最高点,找存在最多子序列
for (let i = 0; i < s.length; i++) {
for (let j = 0; j < i; j++) {
if (s[j] < s[i]) {
dp[i] = Math.max(dp[i], dp[j] + 1);
}
}
}
return dp;
};
const leftArr = dpFn(lineArr); //从小到大
const rightArr = dpFn([...lineArr].reverse()).reverse(); //从大到小
const finArr = []; //组合成一个由低到高再到低
const n = Number(arr[0][0]); //学生数量
for (let i = 0; i < n; i++) {
finArr[i] = leftArr[i] + rightArr[i] - 1;
}
console.log(n - Math.max(...finArr));
})();