力扣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 1target.length,arr.length105
  • 1 ≤ t a r g e t [ i ] , a r r [ i ] ≤ 1 0 9 1 \\leq target[i], arr[i] \\leq 10^9 1target[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之路

1713. 得到子序列的最少操作次数(最长上升子序列问题)

1713. 得到子序列的最少操作次数(最长上升子序列问题)

最长递增子序列&&得到子序列的最少次数

《LeetCode之每日一题》:108.得到子序列的最少操作次数

LeetCode1143. 最长公共子序列/300. 最长递增子序列//1713. 得到子序列的最少操作次数(好题!!!!!)