zoukankan      html  css  js  c++  java
  • leetcode 面试题 17.08. 马戏团人塔+面试题 08.13. 堆箱子 最长不下降子序列以及O(nlogn)优化

    话不多说直接上题



    分析一下,题目要求的是能让所有的箱子竖着堆起来
    下面的箱子要比上面的箱子的三维正经的都要大
    很明显也就是求一个箱子的摆放序列,使得三维递增
    这很明显是一个最长递增子序列问题,那么我们可以
    怎么做呢,因为数据量不大,只有3000,直接n^2的dp
    就行,先将所有的箱子按照第一维升序排序(很重要)
    然后对每一个箱子i,求它作为最下面的时候的最大高度
    需要注意的是必须要排序,不然的话此时i作为最下面
    不一定是最优的~
    ~应该也可以不排序,只不过这时候要对于每个箱子遍历所有的其他箱子~~
    于是就有以下的转移方程dp[i] = max(dp[i],dp[j]+hi)对于所有的
    三维都小于i的j的箱子


    class Solution {
        public int pileBox(int[][] box) {
        	Arrays.sort(box,(int[] a,int[] b)->{
        		return a[0]-b[0];
        	});
            int[] dp = new int[box.length];
            int ans=0;
            for(int i=0; i<box.length; i++){
                dp[i]=box[i][2];
                for(int j=0; j<i; j++){
                    if(judge(box[j],box[i]))
                        dp[i]=Math.max(dp[i],dp[j]+box[i][2]);
                }
            }
            for(int i:dp){
                ans=Math.max(ans,i);
            }
            return ans;
        }
       boolean judge(int[] a,int[] b){
            return b[0]>a[0]&&b[1]>a[1]&&b[2]>a[2];
        }
    }
    


    很明显,这里要求的是身高体重递增,也是求最长上升子序列的长度
    但是不同的是数据量是10^4, 直接n^2的dp的话会在leetcode超时
    于是就用到了LIS的优化,优化的过程是,不断的去降低长度为i的
    最下面的一个人的体重和身高,这样子下一次进来人的时候,给它
    放到最合适它的那一组就可以了,但是要注意的就是,因为这里要求
    的是所有的人的体重身高都要增加,所以排序的时候,先按体重升序
    然后按照身高降序排列。 于是就有转移方程,假设当前的最长的子序列
    长度是maxlen, 则当遇到一个新的人i,由前面的排序过程,可以知道不会
    被后面身高相同的人更新,因为它更轻,于是有,if weight[i]>dp[maxlen]
    那么dp[maxlen+1]=weight[i],因为它比前面最长的队的人的身高体重都大
    else 就找第一个j st.dp[j]>=wight[i].有这个过程可以知道,dp数组是单调非降得
    甚至是单调递增得,所以这个过程就是可以用二分查找来做,所以最后得总复杂就是o(nlogn)


    import java.util.*;
    class Solution {
        public int bestSeqAtIndex(int[] height, int[] weight) {
            //最长递增子序列
            int[] dp = new int[height.length+1]; 
            List<int[]> person = new ArrayList(height.length);
            for(int i=0; i<height.length; i++){
            	person.add(new int[]{height[i],weight[i]});
            }
            person.sort((int[]a,int[]b)->{
            	return a[0]==b[0]?b[1]-a[1]:a[0]-b[0];
            });
            int maxlen=0;
            int pos=0;
            for(int i=0; i<height.length; i++){
            	if(person.get(i)[1]>dp[maxlen])//可以直接更新
            		dp[++maxlen]=person.get(i)[1];
            	else if(person.get(i)[1]<dp[maxlen]){
            		pos=binarySearch(dp,1,maxlen,person.get(i)[1]);
            		dp[pos]=person.get(i)[1];
            	}	
            }
            return maxlen;
        }
        public int binarySearch(int[]dp,int beg,int end,int tatget){
        	int mid=0;
        	while(beg<end){
                //查找的是第一个大于等于他的
                //不能查找第一个大于他的,因为如果查找第一个大于他的
                //可能这个传递过来的是刚好由这个相等传递过来的
                //那么此时这个体重不能更新这一个
        		mid=beg+((end-beg)>>1);
        		if(dp[mid]>=tatget){
        			end=mid;
                    //这里是要保留右边的,也就是第一个大于等于的
        		}
        		else{
        			beg=mid+1;
        		}
        	}
        	return end;
        }
    }
    
  • 相关阅读:
    Yum与list结合
    DNS辅助
    DHCP中继
    apache+SSL 搭建https
    vsftpd服务器
    根据Eclipse SVN changelog使用ANT自动打增量包
    SHELL 近期学习
    Tomcat源码学习一
    oracle笔记
    Linux 下安装 SVN服务器
  • 原文地址:https://www.cnblogs.com/Crossea/p/12826238.html
Copyright © 2011-2022 走看看