题解 | #合唱队# #最长递增子队列#

合唱队

http://www.nowcoder.com/practice/6d9d69e3898f45169a441632b325c7b4

思路

这里思路参考了一部分https://blog.nowcoder.net/n/3b8f1d7bd4c3457ebd86558b73a5a673?f=comment

因为无法一步知道一个人的左右最长队列,所以先尽可能的考虑到每个人都可能作为中间最高那个人,然后找该人两边的左递增右递队员身高数列。

这里主要是找到每个人的最长左递增右递减队员长度。所以不妨拆开每个人来分析,最后汇总判断。寻找最长队员长度的时候,有点类似于贪心,比如找右边较高者,若存在一位,则把左边的递增队员纳入他的子列,同时判断哪个子队员最长,找出最长的之队员即可。

其实这个题如何判断最长递增数列这种解题思想值得掌握。这个可以变形很多题。

Java代码

import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        while (in.hasNext()) { // 注意 while 处理多个 case
            int a = in.nextInt();//数据行数
            int[] line=new int[a];//用数组接收
            //left[i]表示包含从左到右递增的最长的队员个数
            //比如用例186 186 150 200 160 130 197 200
            //left={1 1 1 2 2 1 3 4},left[6]=3,表示最长递增队员数3,包含本人
            int[] left=new int[a];
            //right同理
            int[] right=new int[a];
            //初始赋值
            for(int i=0;i<a;i++){
                line[i]=in.nextInt();
                left[i]=1;//初始为1表示只有本人
                right[i]=1;               
            }
            int lefttemp=0; //          
            for(int i=1;i<a;i++){
                lefttemp=i;
                for(int j=i-1;j>=0;j--){
                    if(line[j]<line[lefttemp]){
                        if((left[i])<left[j]+1){
                            //若存在比当前队员身高低的,则判断他的最长递增数,
                            //+1表示加上当前队员后的人数
                            //若前面队员本身队员数+1后能大于当前队员数,则引入新的 队列
                            left[i]=left[j]+1;
                        }
                    } 
                }
            }
            for(int i=a-2;i>=0;i--){
                int righttemp=i;
                for(int j=i+1;j<a;j++){
                    if(line[j]<line[righttemp]){
                        if((right[i])<right[j]+1){
                            //类似前面的。
                            right[i]=right[j]+1;
                        }
                    } 
                }
            }
            int max=left[0]+right[0]-1;
            for(int i=0;i<a;i++){
                //找出包含本人的左右最长大的队员数
                //因为本人重复计了一次,则需要减1;
                if(max<left[i]+right[i]-1){
                    max=left[i]+right[i]-1;
                }
            }
            System.out.println(a-max);
        }
    }    
}
全部评论

相关推荐

3 1 评论
分享
牛客网
牛客企业服务