題目描述
計算最少出列多少位同窗,使得剩下的同窗排成合唱隊形
說明:
N位同窗站成一排,音樂老師要請其中的(N-K)位同窗出列,使得剩下的K位同窗排成合唱隊形。
合唱隊形是指這樣的一種隊形:設K位同窗從左到右依次編號爲1,2…,K,他們的身高分別爲T1,T2,…,TK,
則他們的身高知足存在i(1<=i<=K)使得T1<T2<......<Ti-1<Ti>Ti+1>......>TK。
你的任務是,已知全部N位同窗的身高,計算最少須要幾位同窗出列,能夠使得剩下的同窗排成合唱隊形。
輸入描述
整數N
輸出描述
最少須要幾位同窗出列
輸入例子
8
186 186 150 200 160 130 197 200
輸出例子
4
算法實現
import java.util.Scanner;
/**
* Declaration: All Rights Reserved !!!
*/
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Scanner scanner = new Scanner(Main.class.getClassLoader().getResourceAsStream("data.txt"));
while (scanner.hasNext()) {
int n = scanner.nextInt();
int[] arr = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = scanner.nextInt();
}
System.out.println(countChorus(arr));
}
scanner.close();
}
/**
* <pre>
* 解題思路
* 乍一看這道題好像無從下手?難不成要枚舉出全部的狀況才能得出結果。通常來講是不會有那種枚舉全部狀況的題的。
* 實際上這是一道簡單動態規劃的題。可是一眼看上去不是很直觀。題目所謂的合唱隊形就是一個最長上升子序列的拼接。
* 只要求出從隊列首到位置 i 的最長上升子序列長度加上從隊尾開始到位置 i 的最長上升子序列的長度就能求出合唱隊
* 形的總長度。 咱們還知道總的人數,減一下就能得出要出列的人數了。
*
* 求最長上升子序列
* 如今有一個序列,要求他的最長上升子序列。直觀上並非很好求得,反過來看的話就能比較好理解:
* 如今對於總序列裏的第i個元素來講,包含元素i的最長子序列是多少呢?若是i前面有能構成最長上升序列的(設它爲j),
* 並且i數值比j大,那很顯然到第i個元素(包含元素i)的最長子序列是到第j個元素的最長子序列+1;不然到第i個元素
* (包含元素i)的最長子序列就是是1。由於前面沒有比他更小的了,只有自身構成一個子序列。
* </pre>
*
* @param arr
* @return
*/
private static int countChorus(int[] arr) {
int[] ltr = getRiseLongestSequenceLeftToRight(arr);
int[] rtl = getRiseLongestSequenceRightToLeft(arr);
int max = Integer.MIN_VALUE;
for (int i = 0; i < arr.length; i++) {
if (max < ltr[i] + rtl[i]) {
max = ltr[i] + rtl[i] - 1;
}
}
return arr.length - max;
}
private static int[] getRiseLongestSequenceLeftToRight(int[] arr) {
int[] ltr = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
ltr[i] = 1;
for (int j = 0; j < i; j++) {
if (arr[i] > arr[j] && ltr[i] <= ltr[j]) {
ltr[i] = ltr[j] + 1;
}
}
}
return ltr;
}
private static int[] getRiseLongestSequenceRightToLeft(int[] arr) {
int[] rtl = new int[arr.length];
for (int i = arr.length - 1; i >= 0; i--) {
rtl[i] = 1;
for (int j = arr.length - 1; j > i; j--) {
if (arr[i] > arr[j] && rtl[i] <= rtl[j]) {
rtl[i] = rtl[j] + 1;
}
}
}
return rtl;
}
}