最长上升子序列.java

package A类有价值的回顾的;
//(LIS)
/*
 * 5-10 列车调度 (25分)
火车站的列车调度铁轨的结构如下图所示。

两端分别是一条入口(Entrance)轨道和一条出口(Exit)轨道,它们之间有N条平行的轨道。每趟列车从入口可以选择任意一条轨道进入,最后从出口离开。在图中有9趟列车,在入口处按照{8,4,2,5,3,9,1,6,7}的顺序排队等待进入。如果要求它们必须按序号递减的顺序从出口离开,则至少需要多少条平行铁轨用于调度?
输入格式:

输入第一行给出一个整数N (2 \le≤ N \le 10^5≤10
​5
​​ ),下一行给出从1到N的整数序号的一个重排列。数字间以空格分隔。
输出格式:

在一行中输出可以将输入的列车按序号递减的顺序调离所需要的最少的铁轨条数。
输入样例:

9
8 4 2 5 3 9 1 6 7
输出样例:

4

 */
import java.io.BufferedInputStream;
import java.util.Scanner;

public class 最长上升子序列 {


    public static void main(String[] args) {
        int[] dp = new int[100];//c[i]存储的是子序列长度为i的序列最后一个值(实际上子序列长度为i的子序列有多个
        Scanner sc = new Scanner(new BufferedInputStream(System.in));
        int n = sc.nextInt();
        int len = 0;

        /*8 4 2 5 3 9 1 6 7 (3.5) 思路:因为另辟一队的原因是当前的a(包含了顺序)太大不能插入上一队的队尾,下一队的对头一定大于上一队的队尾
         *                         
         *    1 2 4 8  //输入8之后,以8结尾的递增子序列就只有1位,因为4前面是大于4的,所以以4结尾的上升子序列只有4
         *        3 5  //如果此时加入一个3.5,过程是这样的:3.5之所以不插入3后面是因为比3大,此时直接借用3储存的的dp就可以了(而3插入5后面是因为3比1大)
         *   (3.5)6 9
         *          7
         */

        while(n != 0){
            int a = sc.nextInt();
            if(len==0||dp[len-1]<=a)//也就是说当前的a比较大,不能够插入队尾,只能另辟一队
                dp[len++] = a;
            else{
                int l=0,r=len,mid;//这是一个二分查找,寻找能够插入队尾的那一队
                while(l<=r){     
                    mid = (l+r)>>1;//相当于/2
                    if(dp[mid]>a)
                        r = mid-1;
                    else
                        l = mid+1;
                }
                dp[l] = Math.min(dp[l], a);//更新队尾
            }
            n--;
        }
        for(int i=0;i<len;i++){
            System.out.print(dp[i]+" ");
        }System.out.println();
        System.out.println(len);
    }

}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值