转换思维很重要。
问出队的最少人数=留下的最多人数
继续分析。怎么求出留下的最多人呢。
假设第i个人一定留下,作为队伍的“中间个头最高的那个人”。我求出i留下作为最高的人时的最多人数。
然后遍历每个人,就知道了可以留下的最多人。
然后我怎么知道,第i人一定在,并作为“中心”的情况下,队列的最多人数呢?
我求出从左到i的最大增序列人数。求出从右到左的最大增序列人数。这样就知道了i留下,作为“中心”时。队列的最大人数。
那我怎么求单方向的,到i为止的增序列最大人数呢。
假设我求从左到右方向。假设我知道了以i左边的每个人为从左到右的增序列的最后一个人的最大人数。以i为最后一个人的增序列中,倒数第二个人可能是左边的所有人(身高小于i),然后我从符合的人中,获取他的最大增序列人数+1,就行了。
那么我需要从左到右维护一个数组。序号i,数值为x:表示:以第i人为队尾,队伍方向从左到右。身高依次递增的最大队伍长度。
同理,我再维护一个从右到左的类似数组。
然后对应位置求和-1,就是以i人为“中间”最高的人时,队伍的总最大人数。
以每个人为“中心”求出一个数组。挑出最大的那个数。此时,离队的人数最少。
import java.util.Scanner;
public class Demo02 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (in.hasNext()) {
int total = in.nextInt();
int[] arr = new int[total];
int[] fromLeft = new int[total];
int[] fromRight = new int[total];
for (int i = 0; i < total; i++) {
fromLeft[i] = 1;
}
for (int i = 0; i < total; i++) {
fromRight[i] = 1;
}
for (int i = 0; i < total; i++) {
arr[i] = in.nextInt();
}
// 填充从左到右的递增序列的个数统计
for (int i = 1; i < total; i++) {
int max = 1;
for (int j = 0; j <= i - 1; j++) {
if (arr[i] > arr[j]) {
max = Math.max(max, fromLeft[j] + 1);
}
}
fromLeft[i] = max;
}
// 填充从右到左的递增序列的个数统计
for (int i = total - 2; i >= 0; i--) {
int max = 1;
for (int j = total - 1; j > i; j--) {
if (arr[i] > arr[j]) {
max = Math.max(max, fromRight[j] + 1);
}
}
fromRight[i] = max;
}
int max = 0;
for (int i = 0; i < total; i++) {
max = Math.max(max, fromLeft[i] + fromRight[i]);
}
System.out.println(total-max + 1);
}
}
}