Java机试题*:合唱队(动态规划、加强版最长子序列问题)
描述
计算最少出列多少位同学,使得剩下的同学排成合唱队形
说明:
N 位同学站成一排,音乐老师要请其中的 (N - K) 位同学出列,使得剩下的 K 位同学排成合唱队形。
合唱队形是指这样的一种队形:设K位同学从左到右依次编号为 1,2…,K ,他们的身高分别为 T1,T2,…,TK , 则他们的身高满足存在 i (1<=i<=K) 使得 T1<T2<......<Ti-1<Ti>Ti+1>......>TK 。
你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。
注意:不允许改变队列元素的先后顺序 且 不要求最高同学左右人数必须相等
请注意处理多组输入输出!
数据范围: 1 \le n \le 3000 \1≤n≤3000
输入描述:
有多组用例,每组都包含两行数据,第一行是同学的总数 N ,第二行是 N 位同学的身高,以空格隔开
输出描述:
最少需要几位同学出列
import java.util.*; /** * * 思路:1.构建整个合唱队人数。2.获取每个位置,左边最长递增数列、右边递减数列。3.左右数列相加则为总的最大数列,用总人数减之,则是最少要去掉的人数。 * 关键点1:left[0] = 1; right[num - 1] = 1; 故左边递增因从0开始,右边需要从num - 1开始。 * 关键点2:left[i] = 1; right[i] = 1;每个位置初始化长度都是自己本身故为1. * 关键点3:状态转移条件:singer[j] < singer[i],left[i] = Math.max(left[j] + 1, left[i]),因为是按数列关键点1顺序遍历,所以j的长度是确定的,又因为i是最高的,故i相对于j构成的数列加上i自身,必定比j大1; */ public class Main { public static int singer[]; public static void main(String[] args) { Scanner in = new Scanner(System.in); while (in.hasNextInt()) { int num = in.nextInt(); // 合唱团总人数 int[] singer = new int[num]; for (int i = 0; i < num; i++) { singer[i] = in.nextInt(); } // 以每个位置作为最高位置获取左侧最长的递增 // 注意:因为左边数列,left[0]的最长数列是1为固定的长度,所以需要从0开始遍历。 // 右侧递减数列,是num -1是1,是确定的所以从num-1开始遍历,顺序不能改变,否则得到的数列长度是错的, int[] left = new int[num]; left[0] = 1; // 左边0位置,长度初始化为1 for (int i = 0; i < num; i++) { // 每个位置,数列初始长度为1 left[i] = 1; for (int j = 0; j < i; j++) { // 符合条件 if(singer[j] < singer[i]) { // left[j]表示j位置最长递增,left[j] + 1表示:因为i位置身高大于j,故对于i来说,至少比j处大1 // 使用left[j] + 1,与left[i]之前的结果动态比较取最大。 left[i] = Math.max(left[j] + 1, left[i]); } } } // 以每个位置作为最高位置获取右侧最长的递减 int[] right = new int[num]; right[num - 1] = 1; // 右边0位置,长度初始化为1 for (int i = num - 1; i >= 0; i--) { // 每个位置,数列初始长度为1 right[i] = 1; for (int j = num - 1; j > i; j--) { // 符合条件 if(singer[j] < singer[i]) { right[i] = Math.max(right[j] + 1, right[i]); } } } // 左右合并 int[] ret = new int[num]; for (int i = 0; i < num; i++) { // 左右数列都算了本身,所以需要减1 ret[i] = left[i] + right[i] - 1; } // 找到最大的数列,即是去掉人数最少的情况 int max = ret[0]; for (int i = 1; i < num; i++) { if(max < ret[i]) { max = ret[i]; } } System.out.println(num - max); } } }
题目来源:牛客网
参考链接:https://blog.nowcoder.net/n/03e8c2d251294f4fa649bd4c5a5c0f7b
浙公网安备 33010602011771号