首页 > 试题广场 >

合唱队

[编程题]合唱队
  • 热度指数:294924 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解

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

K位同学从左到右依次编号为 1,2…,K ,他们的身高分别为 ,若存在 使得,则称这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

说明

由于不允许改变队列元素的先后顺序,所以最终剩下的队列应该为186 200 160 130或150 200 160 130           
//这里有一个示例需要补充
//8
//1 2 3 1 2 4 5 6
//目前示例没有满足 最高不能为头尾
// 左递增,右递减。最高不能为头尾
let n;
function func(height) {
    const list = [];
    for (let i = 0, l = height.length; i < l; i++) {
        list[i] = 1;
        for (let j = 0; j <= i; j++) {
            if (height[i] > height[j]) {
                list[i] = Math.max(list[i], list[j] + 1);
            }
        }
    }
    return list;
}
while (n = readline()) {
    n = parseInt(n);
    let height = readline().split(' ').map(i => parseInt(i));
    let list1 = func(height);
    let list2 = func(height.reverse()).reverse();
    let list3 = list1.map((i, idx) => i + list2[idx]);
    let max = 0, idx = -1;
    list3.forEach((i, index) => {
        if (index !== 0 && index !== list3.length-1 && list1[index]!==1 && list2[index]!==1) {
            if (max < i) {
                max = i;
                idx = index;
            }
        }
    });
    //print(max)
    //print(list1)
    //print(list2)
    //print(list3)
    console.log(n - (max - 1));
}
发表于 2022-08-31 16:21:41 回复(0)
动态规划
const N = readline()
const hArr = readline().trim().split(' ').map(i => +i)
const left = []
const right = []
for (let i = 0; i < N; i++) {
    left[i] = right[i] = 1
}
for (let i = 1; i < N; i++) {
    let max = left[i]
    for (let j = i - 1; j >= 0; j--) {
        if (hArr[j] < hArr[i]) {
            max = Math.max(max, left[j] + left[i])
        }
    }
    left[i] = max
}
for (let i = N - 2; i >= 0; i--) {
    let max = right[i]
    for (let j = i + 1; j < N; j++) {
        if (hArr[j] < hArr[i]) {
            max = Math.max(max, right[j] + right[i])
        }
    }
    right[i] = max
}
var res = left.reduce((res, l, i) => {
    return Math.max(res, left[i] + right[i] - 1)
}, 0)
print(N - res)


发表于 2022-07-08 22:53:16 回复(0)
readline();
let input = readline();
let a = input.split(' ').map(x => parseInt(x));
function c(a) {
  //p[i]:i元素左边的最大递增序列长度
  //q[i]:i元素右边的最大递减序列长度
  let p = [0], q = [];
  q[a.length - 1] = 0;
  for (let i = 1; i < a.length; i++) {
    let max = -1;
    //第i个元素的p值等于 {k| k<i&&a[k]<a[i]}的最大p值+1
    for (let j = 0; j < i; j++) {
      if (a[i] > a[j] && max < p[j]) {
        max = p[j];
      }
    }
    p[i] = max + 1;
  }

  for (let i = a.length - 2; i >= 0; i--) {
    let max = -1;
    //第i个元素的q值等于 {k| k>i&&a[k]<a[i]}的最大q值+1
    for (let j = a.length - 1; j > i; j--) {
      if (a[i] > a[j] && max < q[j]) {
        max = q[j];
      }
    }
    q[i] = max + 1;
  }
  //剩余最大人数
  let max = 0;
  for (let i = 0; i < a.length; i++) {
    max = Math.max(p[i] + q[i] + 1, max);
  }
  //最小出列人数
  return (a.length - max);
}
console.log(c(a));

发表于 2022-07-04 00:59:46 回复(0)
const n = parseInt(readline())
let arr = readline().split(' ').map(Number)
const fn = arr =>{
    let dp = new Array(arr.length).fill(1)
    for(let i = 0;i<arr.length;i++){
        for(let j = 0;j<i;j++){
            if(arr[i]>arr[j]&&dp[j]+1>dp[i])
                dp[i] = dp[j]+1
        }
    }
    return dp
}
let dp1 = fn(arr)
let dp2 = fn(arr.reverse()).reverse()
let max = Math.max(...arr.map((_,i)=>dp1[i]+dp2[i]-1))
console.log(arr.length-max)

发表于 2022-03-23 15:39:22 回复(0)
wdnmd,好家伙,哪位同学的身高为0,真nm
发表于 2021-12-28 19:45:10 回复(0)