难度:困难。
标签:贪心,数组,哈希表,二分查找。
首先,这道题就是最长公共子序列,我竟然没想到。(虽然会超时)
看了两条提醒:
1.The problem can be reduced to computing Longest Common Subsequence between both arrays.
2. Since one of the arrays has distinct elements, we can consider that these elements describe an arrangement of numbers, and we can replace each element in the other array with the index it appeared at in the first array.
然后,题目变成了求最长升序序列。只想到了用动态规划,但是到每一步i,需要遍历0-i的所有元素,比较复杂,超时了。
超时代码:
class Solution {
public:
int minOperations(vector<int>& target, vector<int>& arr) {
unordered_map<int, int> maps;
for(int i = 0; i < target.size(); ++i)maps[target[i]] = i;
vector<int> new_arr;
for(int i = 0; i < arr.size(); ++i){
int a = arr[i];
if(maps.find(a) != maps.end()){
new_arr.emplace_back(maps[a]);
}
}
// for(int i = 0; i < new_arr.size(); ++i)cout << new_arr[i] << " ";
// cout << endl;
if(new_arr.size() <= 1)return target.size() - new_arr.size();
vector<int> dp(new_arr.size());
dp[0] = 1;
int ans = 0;
for(int i = 1; i < new_arr.size(); ++i){
int temp = 0;
for(int j = 0; j < i; ++j){
if(new_arr[j] < new_arr[i]){
temp = max(temp, dp[j]);
}
}
dp[i] = temp + 1;
ans = max(ans, dp[i]);
}
return target.size() - ans;
}
};
再看最后一条提醒:
3. Then the problem is converted to finding Longest Increasing Subsequence in the second array, which can be done in O(n log n).
看了题解,将arr映射为索引后,将target也用索引表示,这是一个最长公共子序列问题。
但是,由于target是递增的,因此问题是最长递增子序列。
使用贪心+二分查找来完成这个题。
贪心思想:最长递增序列中同等位置的值尽可能小。
d[i] ,表示长度为 i 的最长上升子序列的末尾元素的最小值。
遍历arr(不在target中的元素被忽略,在target中的元素被替换成索引idx),每次在d中查找第一个大于等于idx的值,如果这个值存在,则这个值替换为索引更小的idx,如果不存在,说明d中的索引都比idx小,直接将idx加入d即可。
最终最长递增序列的长度为d的大小。
相似题:300. 最长递增子序列
正确解法:
class Solution {
public:
int minOperations(vector<int>& target, vector<int>& arr) {
unordered_map<int, int> maps;
for(int i = 0; i < target.size(); ++i)maps[target[i]] = i;
vector<int> d;
for(int i = 0; i < arr.size(); ++i){
int a = arr[i];
if(maps.find(a) != maps.end()){
int idx = maps[a];
// 在d中查找第一个大于等于idx的值
auto it = lower_bound(d.begin(), d.end(), idx);
if(it != d.end()){
*it = idx;
}
else{
d.emplace_back(idx);
}
}
}
return target.size() - d.size();
}
};
结果: