1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Solution {
public int maxEnvelopes(int[][] envelopes) {
Arrays.sort(envelopes, (a, b) -> a[0] != b[0] ? a[0] - b[0] : b[1] - a[1]);
List<Integer> tails = new ArrayList<>();
for (int[] envelop : envelopes) {
int targetIdx = binarySearch(tails, envelop[1]);
if (targetIdx + 1 == tails.size()) {
tails.add(envelop[1]);
} else {
tails.set(targetIdx + 1, envelop[1]);
}
}
return tails.size();
}

private int binarySearch(List<Integer> tails, int target) {
int left = 0, right = tails.size() - 1, ans = -1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (tails.get(mid) < target) {
ans = mid;
left = mid + 1;
} else {
right = mid - 1;
}
}
return ans;
}
}

有点儿类似找longest increasing sequence. 但是我们不一定非要按照给的envelop的相对顺序去一个装另一个. 而是可以选完后, 自己决定哪个装哪个. 于是我们就想到既然这样我们让width先递增排列. 这样从左到右width至少是非递减的. 由于width已经是递增, 此时跟据height就找LIS. 但是问题就在于相同width的envelop只能选一个. 比如[2, 3], [2, 4], [2, 5], 我们发现根据height找的LIS是3, 但其实这种情况没有其他的envelop能装其他的, 因此答案应该是1. 那么如何避免这种情况呢? 也就是构成LIS时避免选择相同的width. 一个聪明的做法就是把height倒序再排列. 这样构成的LIS中的任意两个元素肯定不可能来自相同的
width的envelop. 这样就变成了以height为准的LIS了.

时间复杂度: O(nlogn)
空间复杂度: O(n) 可能envelop一直是递增的, list存n个元素.