描述 N 位同学站成一排,音乐老师要请最少的同学出列,使得剩下的 K 位同学排成合唱队形。 通俗来说,能找到一个同学,他的两边的同学身高都依次严格降低的队形就是合唱队形。 例子: 123 124 125 123 121 是一个合唱队形 123 123 124 122不是合唱队形,因为前两名同学身高相等,不符合要求 123 122 121 122不是合唱队形,因为找不到一个同学,他的两侧同学身高递减。 你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。 注意:不允许改变队列元素的先后顺序 且 不要求最高同学左右人数必须相等
找到每个位置的向左递减子序列和向右递减子序列 186 186 150 200 160 130 197 200
向左递减子序列
186 | 186 | 150 | 200 | 160 | 130 | 197 | 200 |
---|
1 | 1 | 1 | 2 | 2 | 1 | 3 | 4 |
向右递减子序列
- 200 右边没有 1
- 197 右边没有比它小的 1
- 130 同理 1
- 160 2
- 200 3
- 150 2
- 186 3
- 186 3
即
186 | 186 | 150 | 200 | 160 | 130 | 197 | 200 |
---|
3 | 3 | 2 | 3 | 2 | 1 | 1 | 1 |
由于计算递减子序列的时候对拐点处多加一,所以合唱队列为 左子序列 + 右子序列 - 1
| 186 | 186 | 150 | 200 | 160 | 130 | 197 | 200 |
---|
向左递减子序列 | 1 | 1 | 1 | 2 | 2 | 1 | 3 | 4 | 向右递减子序列 | 3 | 3 | 2 | 3 | 2 | 1 | 1 | 1 | 合唱队列 | 3 | 3 | 2 | 4 | 3 | 1 | 3 | 4 |
package com.wy.leetcode;
import java.util.*;
import java.util.stream.Collectors;
public class ChorusSort {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
ArrayList<Integer> list = new ArrayList<>();
int i = n;
while (i-- > 0) {
list.add(scanner.nextInt());
}
System.out.println(doChorusSort(list, n));
}
public static int doChorusSort(List<Integer> list, int n) {
HashSet<Integer> results = new HashSet<>();
List<Node> leftNodes = new ArrayList<>();
for (int i = 0; i < n; i++) {
int currentPosition = i;
Integer currentSize = list.get(i);
Node node = new Node(currentSize, currentPosition);
leftNodes.add(node);
Integer length = null;
try {
length = leftNodes.stream()
.filter(node1 -> node1.getSize() < currentSize && node1.getPosition() < currentPosition)
.max(Comparator.comparing(Node::getLength))
.get()
.getLength();
} catch (Exception e) {
length = 0;
}
leftNodes.get(i).setLength(length + 1);
}
List<Node> rightNodes = new ArrayList<>();
for (int i = n - 1; i >= 0 ; i--) {
int currentPosition = i;
Integer currentSize = list.get(i);
Node node = new Node(currentSize, currentPosition);
rightNodes.add(node);
Integer length;
try {
length = rightNodes.stream()
.filter(node1 -> node1.getSize() < currentSize && node1.getPosition() > currentPosition)
.max(Comparator.comparing(Node::getLength))
.get()
.getLength();
} catch (Exception e) {
length = 0;
}
rightNodes.get(n - 1 -i).setLength(length + 1);
results.add(leftNodes.get(i).getLength() + rightNodes.get(n - i -1).getLength() - 1);
}
return n - results.stream().max(Comparator.comparing(Integer::intValue)).get();
}
}
class Node {
private int size;
private int position;
private int length;
public Node(Integer size, Integer position) {
this.size = size;
this.position = position;
}
public Integer getSize() {
return size;
}
public void setSize(Integer size) {
this.size = size;
}
public Integer getPosition() {
return position;
}
public void setPosition(Integer position) {
this.position = position;
}
public Integer getLength() {
return length;
}
public void setLength(Integer length) {
this.length = length;
}
}
|