leetcode 354 Russian Doll Envelopes 二元组最长递增子序列

最近在牛客网听左神讲课,在此记录一下。

题目是leetcode 354. Russian Doll Envelopes

问题:给定一个N*2的二维数组,看作是一个个二元组,例如[[a1,b1],[a2,b2],[a3,b3]], 规定:一个如果想把二元组甲放在二元组乙上,甲中的a值必须大于乙中的a值,甲中的b 值必须大于乙中的b值。如果在二维数组中随意选择二元组,请问二元组最多可以往上摞几个?

例如:[[5,4],[6,4],[6,7],[2,3]], 最大数量可以摞3个,[2,3] => [5,4] => [6,7] 要求:实现时间复杂度O(N*logN)的解法。

解法:这道题的算法原型是最长递增子序列,如果我们确定a的排列,在对b求解他的最长递增子序列即可。求解过程:先按a从小到大进行排序,当a相同时,按b从大到小排序。然后求解b的最长递增子序列。为什么b要按从大到小排列呢?按照最长递增子序列的O(N*logN),当前数大于h数组中末尾的数,我们会添加在h数组中;否则在h中查找第一个大于当前数的数并替换之。所以我们的做法会保证a相等的情况下,b可以有一个最小值,这样可以摞相对多的数。以达到最多,同时避免了a相同b不相同时摞在一起的情况。

package dome;

import java.util.Arrays;
import java.util.Comparator;

public class LeetCode354 {
	/** 二元组 */
	public static class Dot {
		int a, b;

		public Dot(int a, int b) {
			this.a = a;
			this.b = b;
		}
	}

	/*** 比较器 */
	public static class DotComparator implements Comparator<Dot> {
		@Override
		public int compare(Dot o1, Dot o2) {
			if (o1.a == o2.a) {
				return o2.b - o1.b;// 这里按b从大到小排序
			} else {
				return o1.a - o2.a;
			}
		}
	}

	/** 开始查找 */
	private int maxEnvelops(int[][] es) {

		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[] h = new int[es.length];
		h[0] = dots[0].b;
		int hl = 0;// h中数据个数
		int r = 0;
		int l = 0;
		int mid = 0;
		for (int i = 1; i < dots.length; i++) {
			r = hl;
			l = 0;
			while (l <= r) {
				mid = (l + r) / 2;
				if (h[mid] < dots[i].b) {
					l = mid + 1;
				} else {
					r = mid - 1;
				}
			}
			hl = Math.max(hl, l);
			h[l] = dots[i].b;
		}
		return hl + 1;
	}

//	public static void main(String[] args) {
//		int es[][] = { { 4, 5 }, { 4, 6 }, { 6, 7 }, { 2, 3 }, { 1, 1 } };
//		System.out.println(maxEnvelops(es));
//	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值