俄国沙皇问题笔记
来源:互联网 发布:mac版的photoshop cc 编辑:程序博客网 时间:2024/04/29 01:07
给定一个N*2的二维数组,看作是一个个二元组,[a1,b1],[a2,b2],[a3,b3],规定:如果想把一个二元组甲放到二元组乙上,甲中的a值必须大于乙中的a值,甲中的b值必须大于乙中的b值,如果二维数组中随意选择二元组,请问二元组中最多可以往上放多少个?
例如:[[7,8],[5,9],[1,2],[6,4],[8,6]],则最多可以放三个:[1,2]->[6,4]->[7,8]或[1,2]->[6,4]->[8,6]
要求:实现时间复杂度O(N*logN)的解法
铺垫:最长递增子序列求解
例如一个数列:2,1,6,4,5,2,7,4
则其最长递增子序列有4个:1,4,5,7或2,4,5,7等
O(n²)解法:
生成一个辅助数组h[8],这辅助数组的用于存放必须以第i个数字结尾的子序列长度,即求出以任何一个数字结尾的数列的最长递增子序列长度。每个数字都要求解以该数字结尾的最长递增子序列长度,即首先是2,以2结尾的最长递增子序列就是2,则h[0]=1;之后是1,以1结尾的最长递增子序列是1,则h[1]=1;之后是6,以6结尾的最长递增子序列是1,6或者2,6,则h[2]=2,以此类推,则例中的h[8]=[1,1,2,2,3,2,4,3]
O(nlogN)解法:
(ps:看到logN一般就会想到是二分法)
此算法是吧之前的枚举过程加速
生成一个辅助数组h[8],首先对于2,直接将2放入,h[0]=2,此时认为之后的h数组都是无效区,只有h[0]是有效区;遇到1时,在有效区中找第一个大于1的数字,利用二分法,因为有效区的有序的,此时由于2>1,则将2换成1,此时h[0]=1,有效区仍然是h[0];
遇到6,在有效区中找第一个大于6的数,但是由于在有效区中没有找到比6大的数,故此时扩充有效区,此时有效区为[1,6],则以6结尾的有效区中的长度为2;
之后是4,在有效区中找到第一个大于4的数,故将6换为4,此时有效区为[1,4],则以4结尾的最长递增子序列是1,4,长度为2;
之后是5,在有效区中扩充,此时有效区为[1,4,5],以5结尾的最长递增子序列为1,4,5,长度为3;
之后是2,将4换为2,此时有效区为1,2,5,则以2结尾的最长递增子序列为1,2,长度为2;
之后是7,扩充有效区,此时以7结尾的最长递增子序列为1,2,5,7,长度为4;
之后是4,此时,将5换为4,此时最长递增子序列为1,2,4,7,即以4结尾的最长递增子序列长度为3。
h[i]的含义是假设当前遍历到cur,h[i]有效区代表遍历到cur为止,长度为i+1的最长递增子序列的最小末尾是什么数,h数组是维持了最小末尾。
以下求解原题:
一种解法是时间复杂度为O(n²),先按照a升序排序,如果a相等时,以b升序排序,得到一个序列,之后在此序列中对b查找最长递增子序列。
本题时间复杂度为O(nLogN)排序策略是,先按照a的值升序排序,当a相等时,以b降序排序。
生成一个辅助数组h[],此时h中放入的是b的值。在a相等时,只关注b,更新h,h只维持b出现的最小末尾。
例如:[[7,8],[5,9],[1,2],[6,4],[8,6]],则最多可以放三个:[1,2]->[6,4]->[7,8]或[1,2]->[6,4]->[8,6]
要求:实现时间复杂度O(N*logN)的解法
铺垫:最长递增子序列求解
例如一个数列:2,1,6,4,5,2,7,4
则其最长递增子序列有4个:1,4,5,7或2,4,5,7等
O(n²)解法:
生成一个辅助数组h[8],这辅助数组的用于存放必须以第i个数字结尾的子序列长度,即求出以任何一个数字结尾的数列的最长递增子序列长度。每个数字都要求解以该数字结尾的最长递增子序列长度,即首先是2,以2结尾的最长递增子序列就是2,则h[0]=1;之后是1,以1结尾的最长递增子序列是1,则h[1]=1;之后是6,以6结尾的最长递增子序列是1,6或者2,6,则h[2]=2,以此类推,则例中的h[8]=[1,1,2,2,3,2,4,3]
O(nlogN)解法:
(ps:看到logN一般就会想到是二分法)
此算法是吧之前的枚举过程加速
生成一个辅助数组h[8],首先对于2,直接将2放入,h[0]=2,此时认为之后的h数组都是无效区,只有h[0]是有效区;遇到1时,在有效区中找第一个大于1的数字,利用二分法,因为有效区的有序的,此时由于2>1,则将2换成1,此时h[0]=1,有效区仍然是h[0];
遇到6,在有效区中找第一个大于6的数,但是由于在有效区中没有找到比6大的数,故此时扩充有效区,此时有效区为[1,6],则以6结尾的有效区中的长度为2;
之后是4,在有效区中找到第一个大于4的数,故将6换为4,此时有效区为[1,4],则以4结尾的最长递增子序列是1,4,长度为2;
之后是5,在有效区中扩充,此时有效区为[1,4,5],以5结尾的最长递增子序列为1,4,5,长度为3;
之后是2,将4换为2,此时有效区为1,2,5,则以2结尾的最长递增子序列为1,2,长度为2;
之后是7,扩充有效区,此时以7结尾的最长递增子序列为1,2,5,7,长度为4;
之后是4,此时,将5换为4,此时最长递增子序列为1,2,4,7,即以4结尾的最长递增子序列长度为3。
h[i]的含义是假设当前遍历到cur,h[i]有效区代表遍历到cur为止,长度为i+1的最长递增子序列的最小末尾是什么数,h数组是维持了最小末尾。
public static int[] getdp(int[] arr){int[] dp = new int[arr.length]; //以每个数字结尾的最长递增子序列的长度int[] ends = new int[arr.length]; ends[0] = arr[0]; int right = 0; //有效区长度int l = 0; //有效区的左边界int r = 0; //有效区的右边界int m = 0;for(int i = 1; i<arr.length; i++){l = 0;r = right;while(l<=r){//在有效区中找到最后一个比当前数小的位置m = (1+r)/2;if(arr[i] > ends[m]){l = m + 1;}else{r = m - 1;}}right = Math.max(right, 1);//若没有找到,扩充有效区ends[i] = arr[i];dp[i] = 1 + i;//以当前数结尾的最长递增子序列长度}return dp;}
以下求解原题:
一种解法是时间复杂度为O(n²),先按照a升序排序,如果a相等时,以b升序排序,得到一个序列,之后在此序列中对b查找最长递增子序列。
本题时间复杂度为O(nLogN)排序策略是,先按照a的值升序排序,当a相等时,以b降序排序。
生成一个辅助数组h[],此时h中放入的是b的值。在a相等时,只关注b,更新h,h只维持b出现的最小末尾。
import java.util.Arrays;import java.util.Comparator;public class RussianDollEnvelopes{public static class Dot{public int w;public int h;public Dot(int weight, int high){w = weight;h = high;}}public static class DotComparator implements Comparator<Dot>{//定义Dot比较器,若返回-1,则arg0放在前面,若返回1,表示arg1放在前面@Overridepublic int compare(Dot arg0, Dot arg1){if(arg0.w == arg1.w){if(arg0.h == arg1.h){return 0;}else if(arg0.h < arg1.h){return 1;}else{return -1;}}else if(arg0.w < arg1.w){return -1;}else{return 1;}}}public static int maxEnvelopes(int[][] es){if(es == null || es.length == 0 || es[0] == null || es[0],length != 2){return 0;}}Dot[] dots = new Dot[es.length];for(int i =0; i<es.length;i++){dots[i] = new Dot(es[i][0], es[i][1]);}Arrays.sort(dots, new DotComparator());//调用排序方法int[] ends = new int[es.length];ends[0] = dots[0].h;int right = 0;int l = 0;int r = 0;int m = 0;for(int i = 1; i<dots.length;i++){l = 0;r = right;while(l <= r){m = (1+r)/2;if(dots[i].h >ends[m]){l = m + 1;}else{r = m - 1;}}right = Math.max(right, l);ends[1] = dots[1].h;}return right+1;}public static void main(String[] args){//...}
阅读全文
0 0
- 俄国沙皇问题笔记
- 【牛课堂第二季】第一章 俄国沙皇问题
- [视频]Kaspersky:俄国IT业的沙皇
- Yalta-沙皇行宫
- 俄国农民乘法
- 约瑟夫斯 俄国农夫
- 论俄国周边形势与俄国对华策略
- 俄国的创新原理 一
- 俄国的创新理论 三
- 俄国和任何挺好听
- 俄国、波兰的二战史
- 来自俄国的创新理论二
- 俄国农民算法(C语言)
- 普京挥洒自如语重心长:"总统不强 俄国难强"
- 问题笔记
- 问题笔记
- 问题笔记
- 问题笔记
- 用RecyclerView多布局实现购物车+随便逛一逛
- JavaScript的prototype
- python将某一目录下的多个文件合并为一个文件
- DrawerLayout滑动禁止Toolbar点击监听控制
- 关于倒排索引
- 俄国沙皇问题笔记
- ehcache memcache redis
- 干货实操:微服务Spring Cloud 系列(三) Eureka服务消费(Ribbon使用)
- Oracle_SQL语句优化规则
- 关于React Native 启动packager, 停留在Loading dependency graph, done.的问题
- leetcode 53. Maximum Subarray
- win32 进度条实现
- 关于笛卡尔积和sql的一些知识点
- Android着色状态栏实践