Skip to content

Commit dbcdccd

Browse files
committed
feat: add solutions to lc problem: No.0673
No.0673.Number of Longest Increasing Subsequence
1 parent 4180d4f commit dbcdccd

File tree

2 files changed

+521
-1
lines changed

2 files changed

+521
-1
lines changed

solution/0600-0699/0673.Number of Longest Increasing Subsequence/README.md

+271-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,27 @@
4343

4444
<!-- 这里可写通用的实现逻辑 -->
4545

46-
[最长递增子序列](/solution/0300-0399/0300.Longest%20Increasing%20Subsequence/README.md)的变形题,除了原有的 `dp` 数组之外,另加了 `cnt` 数组记录以 `nums[i]` 结尾的最长子序列的个数
46+
这是[最长递增子序列](/solution/0300-0399/0300.Longest%20Increasing%20Subsequence/README.md)的变形题。
47+
48+
**方法一:动态规划**
49+
50+
除了原有的 `dp` 数组之外,另加了 `cnt` 数组记录以 `nums[i]` 结尾的最长子序列的个数。
51+
52+
时间复杂度 O(n²)。
53+
54+
**方法二:树状数组**
55+
56+
树状数组,也称作“二叉索引树”(Binary Indexed Tree)或 Fenwick 树。 它可以高效地实现如下两个操作:
57+
58+
1. **单点更新** `update(x, delta)`: 把序列 x 位置的数加上一个值 delta;
59+
1. **前缀和查询** `query(x)`:查询序列 `[1,...x]` 区间的区间和,即位置 x 的前缀和。
60+
61+
这两个操作的时间复杂度均为 `O(log n)`。当数的范围比较大时,需要进行离散化,即先进行去重并排序,然后对每个数字进行编号。
62+
63+
本题我们使用树状数组 `tree[x]` 来维护以 x 结尾的最长上升子序列的长度,以及该长度对应的子序列个数。
64+
65+
时间复杂度 O(nlogn)。
66+
4767

4868
<!-- tabs:start -->
4969

@@ -72,6 +92,52 @@ class Solution:
7292
return ans
7393
```
7494

95+
```python
96+
class BinaryIndexedTree:
97+
def __init__(self, n):
98+
self.n = n
99+
self.c = [0] * (n + 1)
100+
self.d = [0] * (n + 1)
101+
102+
@staticmethod
103+
def lowbit(x):
104+
return x & -x
105+
106+
def update(self, x, val, cnt):
107+
while x <= self.n:
108+
if self.c[x] < val:
109+
self.c[x] = val
110+
self.d[x] = cnt
111+
elif self.c[x] == val:
112+
self.d[x] += cnt
113+
x += BinaryIndexedTree.lowbit(x)
114+
115+
def query(self, x):
116+
val = cnt = 0
117+
while x:
118+
if self.c[x] > val:
119+
val = self.c[x]
120+
cnt = self.d[x]
121+
elif self.c[x] == val:
122+
cnt += self.d[x]
123+
x -= BinaryIndexedTree.lowbit(x)
124+
return val, cnt
125+
126+
127+
class Solution:
128+
def findNumberOfLIS(self, nums: List[int]) -> int:
129+
s = sorted(set(nums))
130+
m = {v: i for i, v in enumerate(s, 1)}
131+
n = len(m)
132+
tree = BinaryIndexedTree(n)
133+
ans = 0
134+
for v in nums:
135+
x = m[v]
136+
val, cnt = tree.query(x - 1)
137+
tree.update(x, val + 1, max(cnt, 1))
138+
return tree.query(n)[1]
139+
```
140+
75141
### **Java**
76142

77143
<!-- 这里可写当前语言的特殊实现逻辑 -->
@@ -107,6 +173,73 @@ class Solution {
107173
}
108174
```
109175

176+
```java
177+
class Solution {
178+
public int findNumberOfLIS(int[] nums) {
179+
TreeSet<Integer> ts = new TreeSet();
180+
for (int v : nums) {
181+
ts.add(v);
182+
}
183+
int idx = 1;
184+
Map<Integer, Integer> m = new HashMap<>();
185+
for (int v : ts) {
186+
m.put(v, idx++);
187+
}
188+
int n = m.size();
189+
BinaryIndexedTree tree = new BinaryIndexedTree(n);
190+
for (int v : nums) {
191+
int x = m.get(v);
192+
int[] t = tree.query(x - 1);
193+
tree.update(x, t[0] + 1, Math.max(t[1], 1));
194+
}
195+
return tree.query(n)[1];
196+
}
197+
}
198+
199+
class BinaryIndexedTree {
200+
private int n;
201+
private int[] c;
202+
private int[] d;
203+
204+
public BinaryIndexedTree(int n) {
205+
this.n = n;
206+
c = new int[n + 1];
207+
d = new int[n + 1];
208+
}
209+
210+
public void update(int x, int val, int cnt) {
211+
while (x <= n) {
212+
if (c[x] < val) {
213+
c[x] = val;
214+
d[x] = cnt;
215+
} else if (c[x] == val) {
216+
d[x] += cnt;
217+
}
218+
x += lowbit(x);
219+
}
220+
}
221+
222+
public int[] query(int x) {
223+
int val = 0;
224+
int cnt = 0;
225+
while (x > 0) {
226+
if (val < c[x]) {
227+
val = c[x];
228+
cnt = d[x];
229+
} else if (val == c[x]) {
230+
cnt += d[x];
231+
}
232+
x -= lowbit(x);
233+
}
234+
return new int[]{val, cnt};
235+
}
236+
237+
public static int lowbit(int x) {
238+
return x & -x;
239+
}
240+
}
241+
```
242+
110243
### **C++**
111244

112245
```cpp
@@ -138,6 +271,68 @@ public:
138271
};
139272
```
140273
274+
```cpp
275+
class BinaryIndexedTree {
276+
public:
277+
int n;
278+
vector<int> c;
279+
vector<int> d;
280+
281+
BinaryIndexedTree(int _n): n(_n), c(_n + 1), d(n + 1){}
282+
283+
void update(int x, int val, int cnt) {
284+
while (x <= n)
285+
{
286+
if (c[x] < val)
287+
{
288+
c[x] = val;
289+
d[x] = cnt;
290+
}
291+
else if (c[x] == val) d[x] += cnt;
292+
x += lowbit(x);
293+
}
294+
}
295+
296+
vector<int> query(int x) {
297+
int val = 0, cnt = 0;
298+
while (x > 0)
299+
{
300+
if (val < c[x])
301+
{
302+
val = c[x];
303+
cnt = d[x];
304+
}
305+
else if (val == c[x]) cnt += d[x];
306+
x -= lowbit(x);
307+
}
308+
return {val, cnt};
309+
}
310+
311+
int lowbit(int x) {
312+
return x & -x;
313+
}
314+
};
315+
316+
class Solution {
317+
public:
318+
int findNumberOfLIS(vector<int>& nums) {
319+
set<int> s(nums.begin(), nums.end());
320+
int idx = 1;
321+
unordered_map<int, int> m;
322+
for (int v : s) m[v] = idx++;
323+
int n = m.size();
324+
BinaryIndexedTree* tree = new BinaryIndexedTree(n);
325+
for (int v : nums)
326+
{
327+
int x = m[v];
328+
auto t = tree->query(x - 1);
329+
tree->update(x, t[0] + 1, max(t[1], 1));
330+
}
331+
return tree->query(n)[1];
332+
}
333+
};
334+
```
335+
141336
### **Go**
142337

143338
```go
@@ -168,6 +363,81 @@ func findNumberOfLIS(nums []int) int {
168363
}
169364
```
170365

366+
```go
367+
type BinaryIndexedTree struct {
368+
n int
369+
c []int
370+
d []int
371+
}
372+
373+
func newBinaryIndexedTree(n int) *BinaryIndexedTree {
374+
c := make([]int, n+1)
375+
d := make([]int, n+1)
376+
return &BinaryIndexedTree{n, c, d}
377+
}
378+
379+
func (this *BinaryIndexedTree) lowbit(x int) int {
380+
return x & -x
381+
}
382+
383+
func (this *BinaryIndexedTree) update(x, val, cnt int) {
384+
for x <= this.n {
385+
if this.c[x] < val {
386+
this.c[x] = val
387+
this.d[x] = cnt
388+
} else if this.c[x] == val {
389+
this.d[x] += cnt
390+
}
391+
x += this.lowbit(x)
392+
}
393+
}
394+
395+
func (this *BinaryIndexedTree) query(x int) []int {
396+
var val, cnt int
397+
for x > 0 {
398+
if val < this.c[x] {
399+
val = this.c[x]
400+
cnt = this.d[x]
401+
} else if val == this.c[x] {
402+
cnt += this.d[x]
403+
}
404+
x -= this.lowbit(x)
405+
}
406+
return []int{val, cnt}
407+
}
408+
409+
func findNumberOfLIS(nums []int) int {
410+
s := make(map[int]bool)
411+
for _, v := range nums {
412+
s[v] = true
413+
}
414+
var t []int
415+
for v, _ := range s {
416+
t = append(t, v)
417+
}
418+
sort.Ints(t)
419+
m := make(map[int]int)
420+
for i, v := range t {
421+
m[v] = i + 1
422+
}
423+
n := len(m)
424+
tree := newBinaryIndexedTree(n)
425+
for _, v := range nums {
426+
x := m[v]
427+
t := tree.query(x - 1)
428+
tree.update(x, t[0]+1, max(t[1], 1))
429+
}
430+
return tree.query(n)[1]
431+
}
432+
433+
func max(a, b int) int {
434+
if a > b {
435+
return a
436+
}
437+
return b
438+
}
439+
```
440+
171441
### **Rust**
172442

173443
```rust

0 commit comments

Comments
 (0)