Java中的进阶最长上升子序列——LIS

Java中的进阶LIS-260326

嘻嘻我又来了,写完这个就睡觉,我感觉我已经学会了,啊哈哈哈哈!这个没法用语言讲,直接上例题吧。

例题1(FROM 洛谷 P2782)

思路

将南岸北岸想象成两条线,现在有南岸的城市 a1,a2 (a1<a2),在北岸有两个城市 b1,b2,如果 b1>b2 那么航线相交,反之则不相交,具体化可以看下图。所以我们知道,如果我们将南岸城市按升序排列,再求北岸对应的序列中最长上升子序列的长度。

代码实现

这里用到了内部类进行二维数组的排序,想学习可以去看 -> Java中的内部类

java 复制代码
import java.util.*;
import java.io.*;

public class Main{
    static BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    public static void main(String [] args) throws IOException{
        int n = Integer.parseInt(next());
        int [][] city  = new int [n][2];
        for(int i=0;i<n;i++){
            city[i][0] = Integer.parseInt(next());
            city[i][1] = Integer.parseInt(next());
        }
        Arrays.sort(city,(a,b)->Integer.compare(a[0],b[0]));//内部类
        int [] north = new int[n];
        for(int i=0;i<n;i++)
            north[i] = city[i][1];
        List<Integer> t = new ArrayList<>();
        for(int x:north){
            int idx = Collections.binarySearch(t,x);
            if(idx < 0)
                idx = -(idx+1);
            if(idx == t.size())
                t.add(idx,x);
            else t.set(idx,x);
        }
        System.out.print(t.size());
    }
    static String  next() throws IOException{
        while(st==null || !st.hasMoreTokens()){
            String str = bf.readLine();
            if(str == null) return null;
            st = new StringTokenizer(str);
        }
        return st.nextToken();
    }
}

例题2(FROM 洛谷 P)

思路

其实就是要求这个序列中有几个不下降子序列,我们前面基础篇讲过Dilworth 定理 ,想学习的可以去看 -> Java中的最长上升子序列和非递增子序列------LNIS 和 LIS 。Dilworth 定理:在任意有限偏序集(Partially Ordered Set, poset)中,最大反链的大小 = 最小链划分的数量。在本题里就是:最长上升子序列的长度 = 下降子序列数量。

代码实现

java 复制代码
import java.util.*;
public class Main{
    
    public static void main(String [] args){
        Scanner input = new Scanner (System.in);
        int n = input.nextInt();
        int [][] wood = new int [n][2];
        for(int i=0;i<n;i++){
            wood[i][0] = input.nextInt();//l
            wood[i][1] = input.nextInt();//w
        }
        Arrays.sort(wood,(a,b)->{
            if(a[0] != b[0])
                return Integer.compare(b[0],a[0]);//如果长度不一样,按长度降序排序
        return Integer.compare(b[1],a[1]);});//如果长度一样,按宽度降序排序
        int [] w = new int [n];
        for(int i=0;i<n;i++)
            w[i] = wood[i][1];
        List<Integer>t = new ArrayList<>();
        for(int x : w){
            int idx = Collections.binarySearch(t,x);
            if(idx<0)
                idx = -(idx+1);
            if(idx == t.size())
                t.add(idx,x);
            else t.set(idx,x);
        }
        System.out.print(t.size());
    }
}

可能会有的问题:
Q: 为什么本题里使用定理要排序,而基础篇的例题里却没用排序?
A: 这是因为本题中不依赖原始序列的顺序,也就是说,我们可以任意排列这个序列,题里并未设限。而基础版里的那个题,它严格的要求了必须是子序列,依赖原始序列顺序,所以不能排序。

**Q:**为什么在上一题使用内部类的时候,是a0在前,而本题是b0在前

**A:**因为上一个题是升序,本题是降序。至于为什么要降序,这基于题目要求,它要求长度和宽度都必须降序。

相关推荐
codigger几秒前
Java 26 深度解析:一次“性能兑现 + 契约收紧”的版本
java·后端·编程·编程语言
Aurorar0rua2 分钟前
CS50 x 2024 Notes Data structures - 08
c语言·开发语言·学习方法
盖世英雄酱581367 分钟前
格式化成日期为什么提前一天呢,同样的时间点还是非必现???
java·后端
企业数字化笔记7 分钟前
新租户注册成功却不能用?开通状态、初始化恢复与可用性验收
开发语言·python
威哥爱编程8 分钟前
【AI全栈12-05】Spring Boot 用 Tool Calling 让 AI 查实时订单与库存
java·spring boot·后端
Guarding and trust8 分钟前
项目拆解(二):模型输出是‘野‘的——三层兜底+重分析,把AI变成可靠零件
java·人工智能·python·大模型·fastapi·ollama·错误兜底
瑶山10 分钟前
Windows + WSL2 Ubuntu + VS Code配置C++开发环境
开发语言·c++·windows·vscode·wsl
春风霓裳12 分钟前
0xc0000005 = 内存访问违规
java
威哥爱编程15 分钟前
【AI全栈12-06】Spring Boot 用 RAG 搭企业私有知识库问答
java·spring boot·后端
迅猛龙办公室18 分钟前
Python实现获取星期字符串
java·前端·python