时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 50M,其他语言100M 热度指数:10782
本题知识点: Java工程师 C++工程师 iOS工程师 安卓工程师 运维工程师 前端工程师 算法工程师 PHP工程师 测试工程师 快手 排序 动态规划 C++工程师 Java工程师 快手 2019 游戏研发工程师 快手 2019
校招时部分企业笔试将禁止编程题跳出页面,为提前适应,练习时请使用在线自测,而非本地IDE。
题目描述
小明有一袋子长方形的积木,如果一个积木A的长和宽都不大于另外一个积木B的长和宽,则积木A可以搭在积木B的上面。好奇的小明特别想知道这一袋子积木最多可以搭多少层,你能帮他想想办法吗?
定义每一个长方形的长L和宽W都为正整数,并且1 <= W <= L <= INT_MAX, 袋子里面长方形的个数为N, 并且 1 <= N <= 1000000.
假如袋子里共有5个积木分别为 (2, 2), (2, 4), (3, 3), (2, 5), (4, 5), 则不难判断这些积木最多可以搭成4层, 因为(2, 2) < (2, 4) < (2, 5) < (4, 5)。
输入描述:
第一行为积木的总个数 N 之后一共有N行,分别对应于每一个积木的宽W和长L
输出描述:
输出总共可以搭的层数
示例1
输入
复制
5 2 2 2 4 3 3 2 5 4 5
输出
复制
4
解题思路:
先将积木的宽进行从小到大进行排序,然后遍历积木数组,用一个游标start来标记积木的陈层数,用res数组来记录已经搭了的积木的长,在遍历积木数组的同时,如果当前积木的长<=res[start],则可以把该积木放到积木下面,如果长>res[start],则在res数组中进行一次二分查找,如果找到第一个大于等于当前积木长的数则将当前的长去覆盖res的这个数组的值
AC代码:
package Test;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
public class 搭积木 {
public static void main(String[] args) throws IOException {
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
int n=Integer.parseInt(br.readLine());
int[][] vis=new int[n][2];
int[] res=new int[n];
for(int i=0;i<n;i++){
String str=br.readLine();
vis[i][0]=Integer.parseInt(str.split(" ")[0]);
vis[i][1]=Integer.parseInt(str.split(" ")[1]);
}
Arrays.sort(vis,(a,b)->a[0]-b[0]);
int start=0;
for(int i=0;i<n;i++){
if(i==0||res[start-1]<=vis[i][1]){
res[start]=vis[i][1];
start++;
}
else{
int index=lower_bound(res,0,start,vis[i][1]);
res[index]=vis[i][1];
}
}
System.out.println(start);
}
public static int lower_bound(int[] nums,int l,int r,int target)
{
while(l<r){
int mid=(l+r)/2;
if(nums[mid]>=target){
r=mid;
}
else l=mid+1;
}
return l;
}
}