Patience Sorting

原来叫 Patience 是因为这个排序像一个扑克牌游戏,游戏名叫“Patience”,现在流行叫“Solitaire”。可以在电脑上玩玩先。
Patience sorting 最适合解决 Longest Increasing Subsequence (LIS) 问题。
例如 arr = [1,3,3,8,6,7].

长度为4。
如何计算长度为4的 LIS 的个数呢?

i = 0, arr[i] = 1 : len = 1, count(0) = 1. (即count(i))
i = 1, arr[i] = 3 : len = 2, count(1) = 1 (len=1 and arr[k] < arr[i] 的所有count(k) 之和).
len = 2, count(2) = 1.
len = 3, count(3) = count(1) + count(2) = 1 + 1 = 2.
len = 3, count(4) = count(1) + count(2) = 1 + 1 = 2.
len = 4, count(5) = count(4) = 2.

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
public int findNumberOfLIS(int[] nums) {
if (nums.length == 0) {
return 0;
}
int n = nums.length;
int[] count = new int[n];
count[0] = 1;
List<List<Integer>> piles = new ArrayList<>();
piles.add(listOf(0));
for (int i = 1; i < n; i++) {
int j = search(piles, nums[i], nums);
if (j == piles.size()) {
piles.add(listOf(i));
count[i] = countOfLess(piles.get(j - 1), nums[i], nums, count);
} else {
count[i] = count[lastOf(piles.get(j))] + (j > 0 ? countOfLess(piles.get(j - 1), nums[i], nums, count) : 1);
piles.get(j).add(i);
}
}
return count[lastOf(piles.get(piles.size() - 1))];
}

List<Integer> listOf(int x) {
List<Integer> list = new ArrayList<>();
list.add(x);
return list;
}

int search(List<List<Integer>> piles, int x, int[] nums) {
int l = 0, r = piles.size() - 1;
if (nums[lastOf(piles.get(r))] < x) {
return r + 1;
}
while (l < r) {
int mid = l + (r - l) / 2;
if (nums[lastOf(piles.get(mid))] < x) {
l = mid + 1;
} else {
r = mid;
}
}
return r;
}

int lastOf(List<Integer> pile) {
return pile.get(pile.size() - 1);
}

int countOfLess(List<Integer> pile, int x, int[] nums, int[] count) {
int l = 0, r = pile.size() - 1;
if (nums[pile.get(l)] < x) {
return count[pile.get(r)];
}
while (l < r) {
int mid = l + (r - l) / 2;
if (nums[pile.get(mid)] >= x) {
l = mid + 1;
} else {
r = mid;
}
}
return count[lastOf(pile)] - (r > 0 ? count[pile.get(r - 1)] : 0);
}

Reference

https://leetcode.com/problems/number-of-longest-increasing-subsequence/discuss/916196/Python-Short-O(n-log-n)-solution-beats-100-explained