合唱隊

題目描述

計算最少出列多少位同窗,使得剩下的同窗排成合唱隊形
說明:
    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;
    }

}
相關文章
相關標籤/搜索