已知一序列无重复元素,对LCS通过LIS进行优化
Posted C_YCBX Py_YYDS
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了已知一序列无重复元素,对LCS通过LIS进行优化相关的知识,希望对你有一定的参考价值。
题目
题目解析
看完题目,我们可以发现,只需要寻找到两个数组直接的最长公共子序列(LCS),便可知最少操作次数。
- 所以毫不犹豫的写下了
O(n^2)
级别的LCS
代码,然后毫不夸张的栈溢出了(毕竟是困难题总得想办法优化
class Solution {
public:
int minOperations(vector<int> &target, vector<int> &arr) {
int m = target.size(),n = arr.size();
int dp [m+1][n+1];
memset(dp,0,sizeof dp);
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
if(target[i-1]==arr[j-1]){
dp[i][j] = dp[i-1][j-1]+1;
}else{
dp[i][j] = max(dp[i-1][j],dp[i][j-1]);
}
}
}
return m-dp[m][n];
}
};
那么我们到底该如何优化呢?
注意到:target不含重复元素,这就给了我们很大的信息量,通过这个我们可以构造正确的哈希映射,将 target
的值和下标进行映射,然后通过 arr
更新 index
数组,计算 LIS
即可得出正确的 LCS
。
下面的图片描述了原理,但注意的是我这里写反了,应该以 ·target· 作映射。
- 自此我们得出做题思路:
- 映射数组(被映射的不能含重复元素)
- 得出下标数组
- 计算LIS
具体代码实现
class Solution {
public:
int minOperations(vector<int> &target, vector<int> &arr) {
//只能记录target中所有,数组的下标,因为target中无相同元素
unordered_map<int,int>check;
for(int i=0;i<target.size();i++)check[target[i]] = i;
//构造下标数组记录与target的交集元素在target数组中的对应下标,就算arr数组中有相同的元素也不用怕了,多记录一次相同下标即可。
int index[arr.size()];
int sz = 0;
for(auto&& t:arr){
if(check.count(t)){
index[sz++] = check[t];
}
}
if(sz==0)return target.size();
//开始进行通过LIS求取LCS
//dp[i]表示长度为i+1的最长递增子序列的最小数值
int dp[sz];memset(dp,0,sizeof dp);
dp[0] = index[0];
int len = 1;
//注意找到相同大小的得覆盖,因为另一个序列不含重复,所以用寻找左边界方式二分为宜
for(int i=1;i<sz;i++){
int l = 0,r=len;
int target = index[i];
while(l<r){
int mid = (l+r)/2;
if(dp[mid]>=target){
r = mid;
}else{
l = mid+1;
}
}
dp[l] = target;
//别无脑len++,注意判断是否变长
if(l==len)len++;
}
return target.size()-len;
}
};
以上是关于已知一序列无重复元素,对LCS通过LIS进行优化的主要内容,如果未能解决你的问题,请参考以下文章