力扣LeetCode-1713. 得到子序列的最少操作次数-题解-最长递增子序列
Posted Tisfy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了力扣LeetCode-1713. 得到子序列的最少操作次数-题解-最长递增子序列相关的知识,希望对你有一定的参考价值。
力扣LeetCode-1713. 得到子序列的最少操作次数
Problem Description
给你一个数组 t a r g e t target target ,包含若干 互不相同 的整数,以及另一个整数数组 a r r arr arr , a r r arr arr 可能 包含重复元素。
每一次操作中,你可以在 a r r arr arr 的任意位置插入任一整数。比方说,如果 a r r = [ 1 , 4 , 1 , 2 ] arr = [1,4,1,2] arr=[1,4,1,2] ,那么你可以在中间添加 3 3 3 得到 [ 1 , 4 , 3 , 1 , 2 ] [1,4,3,1,2] [1,4,3,1,2] 。你可以在数组最开始或最后面添加整数。
请你返回 最少 操作次数,使得 t a r g e t target target 成为 a r r arr arr 的一个子序列。
一个数组的 子序列 指的是删除原数组的某些元素(可能一个元素都不删除),同时不改变其余元素的相对顺序得到的数组。比方说, [ 2 , 7 , 4 ] [2,7,4] [2,7,4] 是 [ 4 , 2 , 3 , 7 , 2 , 1 , 4 ] [4,2,3,7,2,1,4] [4,2,3,7,2,1,4] 的子序列(加粗元素),但 [ 2 , 4 , 2 ] [2,4,2] [2,4,2] 不是子序列。
Tips
- 1 ≤ t a r g e t . l e n g t h , a r r . l e n g t h ≤ 1 0 5 1 \\leq target.length, arr.length \\leq 10^5 1≤target.length,arr.length≤105
- 1 ≤ t a r g e t [ i ] , a r r [ i ] ≤ 1 0 9 1 \\leq target[i], arr[i] \\leq 10^9 1≤target[i],arr[i]≤109
- t a r g e t target target 不包含任何重复元素。
Sample I
输入:target = [5,1,3], arr = [9,4,2,3,4]
输出:2
解释:你可以添加 5 和 1 ,使得 arr 变为 [5,9,4,1,2,3,4] ,target 为 arr 的子序列。
Sample II
输入:target = [6,4,8,1,3,2], arr = [4,7,6,2,3,8,6,1]
输出:3
解题思路
做这题时不难想到最长递增子序列这道题。如果没看过的可以先看一下。
题目描述中特意说明了 t a r g e t target target数组互不相同,那么我们是否可以把 t a r g e t target target数组映射一下呢?
如果能够把 t a r g e t target target数组映射成单调递增的另一个数组,那么不就变成上一道题了吗
关键在于如何映射。正好,数组中元素的下标是递增的,因此我们可以把 t a r g e t target target中的每一个数映射成它的下标,就变成了最长递增子序列问题。
所以直接用map存一下 t a r g e t target target中的数和它的下标即可。
公共子序列越长,需要删除的就越少( 需 要 删 除 数 = 总 长 度 − 可 保 留 数 需要删除数 = 总长度 - 可保留数 需要删除数=总长度−可保留数)
具体如何实现可以参考一下代码。
AC代码
int d[100010]={0};
class Solution
{
public:
int minOperations(vector<int> &target, vector<int> &arr)
{
int len=0; // d的初始长度
map<int,int>loc;
for(int i=0;i<target.size();i++)
{
loc[target[i]]=i; // 记录下target中的元素和它的下标的对应关系
}
vector<int>nums; // arr中可能有target中不存在的数,把nums中在target中存在的数映射成该数在target中的下标
for(int i=0;i<arr.size();i++)
{
if(loc.count(arr[i])) // 如果在target中存在
{
nums.push_back(loc[arr[i]]);
}
}
if(nums.size()) // 如果非空
{
d[len++]=nums[0]; // 第一个元素一定可以放入
for(int i=1;i<nums.size();i++) // 遍历
{
int thisNum=nums[i]; // 这个数
if(thisNum>d[len-1]) // 如果大于d中的最后一个数
{
d[len++]=thisNum; // 添加到后面
}
else // 否则
{
int *it=lower_bound(d, d+len, thisNum); // 找到第一个大于等于这个数的位置
*it = thisNum; // 用这个数替换原本比它大的数。
}
}
}
return target.size()-len; // 需要删除数 = 总长度 - 可保留数
}
};
原创不易,转载请附上原文链接哦~
Tisfy:https://letmefly.blog.csdn.net/article/details/119108433
以上是关于力扣LeetCode-1713. 得到子序列的最少操作次数-题解-最长递增子序列的主要内容,如果未能解决你的问题,请参考以下文章
LeetCode 1713 得到子序列的最少操作次数[Map 二分法] HERODING的LeetCode之路
《LeetCode之每日一题》:108.得到子序列的最少操作次数
LeetCode1143. 最长公共子序列/300. 最长递增子序列//1713. 得到子序列的最少操作次数(好题!!!!!)