题解 | #合唱队#
合唱队
https://www.nowcoder.com/practice/6d9d69e3898f45169a441632b325c7b4
import java.util.Arrays; import java.util.List; import java.util.Objects; import java.util.Scanner; import java.util.stream.Collectors; /** * 8 * 186 186 150 200 160 130 197 200 * 4 * 说明: * 由于不允许改变队列元素的先后顺序,所以最终剩下的队列应该为186 200 160 130或150 200 160 130 */ public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); while (in.hasNextLine()) { String nextLine = in.nextLine(); if (Objects.isNull(nextLine) || nextLine.equals("")) { break; } int n = Integer.parseInt(nextLine); String line = in.nextLine(); List<Integer> student = Arrays.stream(line.split(" ")) .map(Integer::parseInt) .collect(Collectors.toList()); // dp表示当前状态队伍中,当前人为最高点时,队伍的最多递增人数 // 左边人数 int[] dpLeft = new int[student.size()]; // 右边的人数 int[] dpRight = new int[student.size()]; // 初始化 // 当队伍里面只有1个人时,最终队伍人数就是1 dpLeft[0] = 1; dpRight[student.size() - 1] = 1; // 初始最终只有1个人 int result = 1; // 左队伍人数逐渐增加,刷新状态 for (int i = 0; i < student.size(); i++) { // 先默认自成一派 dpLeft[i] = 1; // 当前人的高度 Integer current = student.get(i); // 如果当前的人比前一个遍历还高或者跟它一样高 // 如果当前的人比前一个遍历还矮,则它的dpLeft值应当是dpLeft中比前一个状态稍微矮一个级的+1 for (int j = 0; j < i; j++) { if (student.get(j) < current) { dpLeft[i] = Math.max(dpLeft[i], dpLeft[j] + 1); } } } // 右队伍人数逐渐增加,刷新状态 for (int i = student.size() - 1; i >= 0; i--) { // 先默认自成一派 dpRight[i] = 1; // 当前人的高度 Integer current = student.get(i); // 如果当前的人比前一个遍历还高或者跟它一样高 // 如果当前的人比前一个遍历还矮,则它的dpLeft值应当是dpLeft中比前一个状态稍微高一个级的+1 for (int j = student.size() - 1; j > i; j--) { if (student.get(j) < current) { dpRight[i] = Math.max(dpRight[i], dpRight[j] + 1); } } } // 左队伍+右队伍,遍历出最大值 for (int i = 0; i < student.size() - 1; i++) { result = Math.max(dpLeft[i] + dpRight[i], result); } // 需要减去中间那个重复的人,合唱队队伍人数最多 System.out.println(student.size() - result+1); } } }