「这是我参与2022首次更文挑战的第16天,活动详情查看:2022首次更文挑战」。
题目描述
这是leetcode上的一道面试题,题解思路如下
题解
这道题目题解分两步
1. 排序
按某一维度进行排序,这里用高度进行排序,同时需要注意,上升子序列不能身高和体重有任一相同的情况,所以在高度相同的情况下要按体重降序(按体重降序的话接下来只需要weight[i]>weight[i-1],就可以排除身高或体重相同的情况,因为如果weight[i]>weight[i-1]的话身高一定不同(身高相同与排序结果相斥)
2.最长上升子序列
- 维护一个单调栈(用数组实现)F[N]
- 原数组A[N],遍历A,如果F为空或栈顶元素小于A[i],那么直接入栈,否则通过二分查找找到第一个大于或等于A[i]的数然后将其替换为A[i]。这里简单理解一下,将前面元素用A[i]替换后后面的元素将更有机会加入到该单调栈中。
- 最后返回栈的大小就可以了。
class Solution {
class Node{
int height;
int weight;
Node(int height,int weight){
this.height=height;
this.weight=weight;
}
}
//找到第一个大于或等于key的数
public int upperBound(int[] arrays,int length,int key){
int l=0;
int r=length-1;
while(l<=r){//最终会有l==r的情况,此时不管l右移还是r左移都会有arrays[l]>=key
int mid=(l+r)/2;
if(arrays[mid]<key)l=mid+1;
else{
//由于求得是第一个大于等于key的数,所以应该让区间往左。
r=mid-1;
}
}
return l;
}
public int bestSeqAtIndex(int[] height, int[] weight) {
Node[] nodes=new Node[height.length];
for (int i = 0; i < nodes.length; i++) {
nodes[i]=new Node(height[i],weight[i]);
}
Arrays.sort(nodes, new Comparator<Node>() {
@Override
public int compare(Node o1, Node o2) {
if(o1.height==o2.height)return o2.weight-o1.weight;
return (o1.height-o2.height);
}
});
int[] ans=new int[weight.length];
int size=0;
for (int i = 0; i < nodes.length; i++) {
if(i==0)ans[size++]=nodes[i].weight;
else{
if(nodes[i].weight>ans[size-1]){
ans[size++]=nodes[i].weight;
}else{
int pos=upperBound(ans,size,nodes[i].weight);
ans[pos]=nodes[i].weight;
}
}
}
return size;
}
}
找到第一个大于等于key的数(二分)
//找到第一个大于或等于key的数
public int upperBound(int[] arrays,int length,int key){
int l=0;
int r=length-1;
while(l<=r){//最终会有l==r的情况,此时不管l右移还是r左移都会有arrays[l]>=key
int mid=(l+r)/2;
if(arrays[mid]<key)l=mid+1;
else{
//由于求得是第一个大于等于key的数,所以应该让区间往左。
r=mid-1;
}
}
return l;
}