Skip to content

Commit 53ab452

Browse files
committed
feat: add solutions to lc problem: No.1713
No.1713.Minimum Operations to Make a Subsequence
1 parent 2c34080 commit 53ab452

File tree

7 files changed

+761
-1
lines changed

7 files changed

+761
-1
lines changed

solution/0300-0399/0300.Longest Increasing Subsequence/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@
7575
设当前求出的最长上升子序列的长度为 size,初始 `size = 1`,从前往后遍历数组 nums,在遍历到 `nums[i]` 时:
7676

7777
-`nums[i] > d[size]`,则直接将 `nums[i]` 加入到数组 d 的末尾,并且更新 size 自增;
78-
- 否则,在数组 d 中二分查找(前面证明 d 是一个单调递增数组),找到第一个大于等于 nums[i] 的位置 idx,更新 `d[idx] = nums[i]`
78+
- 否则,在数组 d 中二分查找(前面证明 d 是一个单调递增数组),找到第一个大于等于 `nums[i]` 的位置 idx,更新 `d[idx] = nums[i]`
7979

8080
最终返回 size。
8181

solution/1700-1799/1713.Minimum Operations to Make a Subsequence/README.md

Lines changed: 264 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,22 +43,286 @@
4343

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

46+
**方法一:最长递增子序列**
47+
48+
根据题意,`target``arr` 这两个数组的公共子序列越长,需要添加的元素就越少。因此,最少添加的元素个数等于 `target` 的长度减去 `target``arr` 的最长公共子序列的长度。
49+
50+
但是,[求最长公共子序列](/solution/1100-1199/1143.Longest%20Common%20Subsequence/README.md)的时间复杂度为 $O(mn)$,无法通过本题,需要转变思路。
51+
52+
我们可以用一个哈希表记录 `target` 数组中每个元素的下标,然后遍历 `arr` 数组,对于 `arr` 数组中的每个元素,如果哈希表中存在该元素,则将该元素的下标加入到一个数组中,这样就得到了一个新的数组 `nums`,该数组是 `arr` 中的元素在 `target` 数组中的下标(去掉了不在 `target` 中的元素),该数组的最长递增子序列的长度就是 `target``arr` 的最长公共子序列的长度。
53+
54+
因此,问题转化为求 `nums` 数组的最长递增子序列的长度。参考 [300. 最长递增子序列](/solution/0300-0399/0300.Longest%20Increasing%20Subsequence/README.md)
55+
56+
时间复杂度 $O(n\log n)$,其中 $n$ 为 `arr` 数组的长度。
57+
4658
<!-- tabs:start -->
4759

4860
### **Python3**
4961

5062
<!-- 这里可写当前语言的特殊实现逻辑 -->
5163

5264
```python
65+
class BinaryIndexedTree:
66+
def __init__(self, n):
67+
self.n = n
68+
self.c = [0] * (n + 1)
69+
70+
@staticmethod
71+
def lowbit(x):
72+
return x & -x
73+
74+
def update(self, x, val):
75+
while x <= self.n:
76+
self.c[x] = max(self.c[x], val)
77+
x += BinaryIndexedTree.lowbit(x)
78+
79+
def query(self, x):
80+
s = 0
81+
while x:
82+
s = max(s, self.c[x])
83+
x -= BinaryIndexedTree.lowbit(x)
84+
return s
5385

86+
87+
class Solution:
88+
def minOperations(self, target: List[int], arr: List[int]) -> int:
89+
d = {v: i for i, v in enumerate(target)}
90+
nums = [d[v] for v in arr if v in d]
91+
return len(target) - self.lengthOfLIS(nums)
92+
93+
def lengthOfLIS(self, nums):
94+
s = sorted(set(nums))
95+
m = {v: i for i, v in enumerate(s, 1)}
96+
tree = BinaryIndexedTree(len(m))
97+
ans = 0
98+
for v in nums:
99+
x = m[v]
100+
t = tree.query(x - 1) + 1
101+
ans = max(ans, t)
102+
tree.update(x, t)
103+
return ans
54104
```
55105

56106
### **Java**
57107

58108
<!-- 这里可写当前语言的特殊实现逻辑 -->
59109

60110
```java
111+
class BinaryIndexedTree {
112+
private int n;
113+
private int[] c;
114+
115+
public BinaryIndexedTree(int n) {
116+
this.n = n;
117+
this.c = new int[n + 1];
118+
}
119+
120+
public static int lowbit(int x) {
121+
return x & -x;
122+
}
123+
124+
public void update(int x, int val) {
125+
while (x <= n) {
126+
c[x] = Math.max(c[x], val);
127+
x += lowbit(x);
128+
}
129+
}
130+
131+
public int query(int x) {
132+
int s = 0;
133+
while (x > 0) {
134+
s = Math.max(s, c[x]);
135+
x -= lowbit(x);
136+
}
137+
return s;
138+
}
139+
}
140+
141+
class Solution {
142+
public int minOperations(int[] target, int[] arr) {
143+
Map<Integer, Integer> d = new HashMap<>();
144+
for (int i = 0; i < target.length; ++i) {
145+
d.put(target[i], i);
146+
}
147+
List<Integer> nums = new ArrayList<>();
148+
for (int i = 0; i < arr.length; ++i) {
149+
if (d.containsKey(arr[i])) {
150+
nums.add(d.get(arr[i]));
151+
}
152+
}
153+
return target.length - lengthOfLIS(nums);
154+
}
155+
156+
private int lengthOfLIS(List<Integer> nums) {
157+
TreeSet<Integer> ts = new TreeSet();
158+
for (int v : nums) {
159+
ts.add(v);
160+
}
161+
int idx = 1;
162+
Map<Integer, Integer> d = new HashMap<>();
163+
for (int v : ts) {
164+
d.put(v, idx++);
165+
}
166+
int ans = 0;
167+
BinaryIndexedTree tree = new BinaryIndexedTree(nums.size());
168+
for (int v : nums) {
169+
int x = d.get(v);
170+
int t = tree.query(x - 1) + 1;
171+
ans = Math.max(ans, t);
172+
tree.update(x, t);
173+
}
174+
return ans;
175+
}
176+
}
177+
```
178+
179+
### **C++**
180+
181+
```cpp
182+
class BinaryIndexedTree {
183+
public:
184+
int n;
185+
vector<int> c;
186+
187+
BinaryIndexedTree(int _n): n(_n), c(_n + 1){}
188+
189+
void update(int x, int val) {
190+
while (x <= n)
191+
{
192+
c[x] = max(c[x], val);
193+
x += lowbit(x);
194+
}
195+
}
196+
197+
int query(int x) {
198+
int s = 0;
199+
while (x > 0)
200+
{
201+
s = max(s, c[x]);
202+
x -= lowbit(x);
203+
}
204+
return s;
205+
}
206+
207+
int lowbit(int x) {
208+
return x & -x;
209+
}
210+
};
211+
212+
class Solution {
213+
public:
214+
int minOperations(vector<int>& target, vector<int>& arr) {
215+
unordered_map<int, int> d;
216+
for (int i = 0; i < target.size(); ++i) d[target[i]] = i;
217+
vector<int> nums;
218+
for (int i = 0; i < arr.size(); ++i) {
219+
if (d.count(arr[i])) {
220+
nums.push_back(d[arr[i]]);
221+
}
222+
}
223+
return target.size() - lengthOfLIS(nums);
224+
}
225+
226+
int lengthOfLIS(vector<int>& nums) {
227+
set<int> s(nums.begin(), nums.end());
228+
int idx = 1;
229+
unordered_map<int, int> d;
230+
for (int v : s) d[v] = idx++;
231+
BinaryIndexedTree* tree = new BinaryIndexedTree(d.size());
232+
int ans = 0;
233+
for (int v : nums) {
234+
int x = d[v];
235+
int t = tree->query(x - 1) + 1;
236+
ans = max(ans, t);
237+
tree->update(x, t);
238+
}
239+
return ans;
240+
}
241+
};
242+
```
243+
244+
### **Go**
245+
246+
```go
247+
type BinaryIndexedTree struct {
248+
n int
249+
c []int
250+
}
251+
252+
func newBinaryIndexedTree(n int) *BinaryIndexedTree {
253+
c := make([]int, n+1)
254+
return &BinaryIndexedTree{n, c}
255+
}
256+
257+
func (this *BinaryIndexedTree) lowbit(x int) int {
258+
return x & -x
259+
}
260+
261+
func (this *BinaryIndexedTree) update(x, val int) {
262+
for x <= this.n {
263+
if this.c[x] < val {
264+
this.c[x] = val
265+
}
266+
x += this.lowbit(x)
267+
}
268+
}
269+
270+
func (this *BinaryIndexedTree) query(x int) int {
271+
s := 0
272+
for x > 0 {
273+
if s < this.c[x] {
274+
s = this.c[x]
275+
}
276+
x -= this.lowbit(x)
277+
}
278+
return s
279+
}
280+
281+
func minOperations(target []int, arr []int) int {
282+
d := map[int]int{}
283+
for i, v := range target {
284+
d[v] = i
285+
}
286+
nums := []int{}
287+
for _, v := range arr {
288+
if i, ok := d[v]; ok {
289+
nums = append(nums, i)
290+
}
291+
}
292+
return len(target) - lengthOfLIS(nums)
293+
}
294+
295+
func lengthOfLIS(nums []int) int {
296+
s := map[int]bool{}
297+
for _, v := range nums {
298+
s[v] = true
299+
}
300+
t := []int{}
301+
for v := range s {
302+
t = append(t, v)
303+
}
304+
sort.Ints(t)
305+
d := map[int]int{}
306+
for i, v := range t {
307+
d[v] = i + 1
308+
}
309+
tree := newBinaryIndexedTree(len(d))
310+
ans := 0
311+
for _, v := range nums {
312+
x := d[v]
313+
t := tree.query(x-1) + 1
314+
ans = max(ans, t)
315+
tree.update(x, t)
316+
}
317+
return ans
318+
}
61319
320+
func max(a, b int) int {
321+
if a > b {
322+
return a
323+
}
324+
return b
325+
}
62326
```
63327

64328
### **...**

0 commit comments

Comments
 (0)