21 俄罗斯套娃信封问题

问题描述,给你一个二维数组envelopes,其中envelopes[i]=[wi,hi].表示第i个信封的宽度和高度,当另一个信封的宽度和噶度都比这个信封大的时候就可以放进另一个信封里,如同俄罗斯套娃一样。请计算最多能有多少个信封能组成一套“俄罗斯套娃一样”

问题分析求解:要求w和h都要求从大到小进行排列,可以先依据w进行升序排列,而后求解排列后的数组h的最大上升子序列即可,上升子序列可以采用动态规划dp[i]表示以i结尾的最大上升子序列长度,在一个循环中求最值

pubic int MaxEnvelope(int [][]envelopes)
{
//首先对于envelopes的每个元素进行排序
Arrays.sort(envelopes,(int[]arr1,int[]arr2)->
{
if(arr1[0]==arr2[0])
{
return arr1[1]-arr2[1];
}else
{
return arr1[0]-arr2[1];
}
});
//使用动态规划求解
int []dp=new int[envelopes.length];
dp[0]=1;
Arrays.fill(dp,1);
int max=Integer.MIN_VALUE;
for(int i=1;i0;j--)
{
if(envelopes[i][1]>envelopes[j][1])
{
dp[i]=Math.max(dp[j]+1,dp[i]);
max=Math.max(max,dp[i]);
}
}
}
​​​​​​​return max;
}

使用单调栈进行优化,由于是求最长递增子列,从而可以进行求解

public int maxEnvelope(int[][]envelopes)
{
Arrays.sort(envelopes,(int[]arr1,int[]arr2)->
{
if(arr1[0]==arr2[0])
{
return arr1[1]-arr2[1];
}else
{
return arr1[0]-arr2[0];
}
});
List list=new LinkedList<>(envelopes.length);
list.add(envelopes[0][1]);
for(int i=1;i {
if(envelopes[i][1]>list.get(list.size()-1))
{
list.add(envelopes[i][1]);
}else
{
int index=Collections.binarySearch(list,envelopes[i][1]);
if(index>0)
{
list.set(index,envelopes[i][1]);
}
else
{
list.set(-index-1,envelopes[i][1]);
}
}
}
return list.size();
}

新知识总结:申请一个链表 LinkedListlist=new LinkedList<>(nums.length);数组排序Arrays.sort(int[][],(int[],int[])->{})或Arrays.sort(int[],(int,int)->{}),数组填充,Arrays.fill(int[],value);
链表插入list.add(),链表替换list.set(index,value);二分法查找,Collections.binarySearch(list,value),若存在则返回整数,若不存则返回复数,通过(-index-1)可以找到第一个大于其的位置。

你可能感兴趣的:(JAVA刷题500道,java,eclipse,动态规划,算法)