C++二分算法:得到子序列的最少操作次數

本文涉及的基礎知識點

二分查找算法合集

題目

給你一個數組 target ,包含若干 互不相同 的整數,以及另一個整數數組 arr ,arr 可能 包含重復元素。
每一次操作中,你可以在 arr 的任意位置插入任一整數。比方說,如果 arr = [1,4,1,2] ,那么你可以在中間添加 3 得到 [1,4,3,1,2] 。你可以在數組最開始或最后面添加整數。
請你返回 最少 操作次數,使得 target 成為 arr 的一個子序列。
一個數組的 子序列 指的是刪除原數組的某些元素(可能一個元素都不刪除),同時不改變其余元素的相對順序得到的數組。比方說,[2,7,4] 是 [4,2,3,7,2,1,4] 的子序列(加粗元素),但 [2,4,2] 不是子序列。
示例 1:
輸入:target = [5,1,3], arr = [9,4,2,3,4]
輸出:2
解釋:你可以添加 5 和 1 ,使得 arr 變為 [5,9,4,1,2,3,4] ,target 為 arr 的子序列。
示例 2:
輸入:target = [6,4,8,1,3,2], arr = [4,7,6,2,3,8,6,1]
輸出:3
參數范圍
1 <= target.length, arr.length <= 105
1 <= target[i], arr[i] <= 109
target 不包含任何重復元素。

分析

時間復雜度

O(nlogn),枚舉arr的時間復雜度O(n),處理arr的每個元素都需要二分查找,時間復雜度O(n)。

最長公共子序列

本題轉換一下就是:求 target的長度減兩者的公共最長子序列的長度。

注意

target 中沒有重復的元素,所以可以將nums[i]替換成它的索引。比如: target= {3,2,1},arr={2,3}。
替換成{0,1,2},{1,0}。arr存在,但target中不存在的元素,忽略掉,比如:設置為-1,處理的時候忽略掉。

大致步驟。

一,值變索引。

 mValueIndex[target[i]] = i;

二,依次枚舉arr[i]。

for (const auto& n : arr)

vLenToEndIndex

vLenToEndIndex見的淘汰

vLenToEndIndex[i]如果有多個值,淘汰值大的。因為索引越小越容易組成新的子序列。

含義

vLenToEndIndex[i]為j,表示目前長度為i+1的子序列的末尾元素的值(同時也是target中的索引)是j。
構建以n結果的公共子序列的兩者方法:

只有n一個元素的子序列
如果存在j<n,且以j結尾的公共序列此系列+i

令n在 arr中的索引為i,則除掉被淘汰的公共子序列,以arr[0,i)結尾的公共子序列都在vLenToEndIndex中。vLenToEndIndex[j]小于n,說明vLenToEndIndex[j]在target的位置在n之前。也就是此子系列的結尾元素在target和arr中,都在n之前,故可以組成新的子序列。如果有多個vLenToEndIndex[j]符合條件取最大j。j+1就是新系列的長度。

vLenToEndIndex是嚴格遞增

一,初始狀態下,空向量符合嚴格遞增。
二,如果vLenToEndIndex所有元素小于n,則n追加到最后,顯然是嚴格遞增。
三,it是第一個大于等于n的數。也就是a,it之前的數都小于n。b,由于vLenToEndIndex是嚴格遞增,所有it后面的數大于it,而it>=n,故后面的元素>n。所以以下代碼不會影響嚴格遞增。

*it = n;

代碼

核心代碼

class Solution {
public:
int minOperations(vector& target, vector& arr) {
unordered_map<int, int> mValueIndex;
for (int i = 0; i < target.size(); i++)
{
mValueIndex[target[i]] = i;
}
for (auto& n : arr)
{
if (mValueIndex.count(n))
{
n = mValueIndex[n];
}
else
{
n = -1;
}
}
vector vLenToEndIndex;
for (const auto& n : arr)
{
if (-1 == n)
{
continue;
}
auto it = std::lower_bound(vLenToEndIndex.begin(), vLenToEndIndex.end(), n);
if (vLenToEndIndex.end() == it)
{
vLenToEndIndex.emplace_back(n);
}
else
{
if (n < *it)
{
*it = n;
}
}
}
return target.size() - vLenToEndIndex.size();
}
};

優化后的代碼

直接將符合的arr[i]復制到新數組中。

class Solution {
public:int minOperations(vector<int>& target, const vector<int>& arr) {unordered_map<int, int> mValueIndex;for (int i = 0; i < target.size(); i++){mValueIndex[target[i]] = i;}vector<int> vNew;for (auto& n : arr){if (mValueIndex.count(n)){vNew.emplace_back(mValueIndex[n]);}}vector<int> vLenToEndIndex;for (const auto& n : vNew){auto it = std::lower_bound(vLenToEndIndex.begin(), vLenToEndIndex.end(), n);if (vLenToEndIndex.end() == it){vLenToEndIndex.emplace_back(n);}else{if (n < *it){*it = n;}}}return target.size() - vLenToEndIndex.size();}
};

測試用例

template
void Assert(const T& t1, const T& t2)
{
assert(t1 == t2);
}

template
void Assert(const vector& v1, const vector& v2)
{
if (v1.size() != v2.size())
{
assert(false);
return;
}
for (int i = 0; i < v1.size(); i++)
{
Assert(v1[i], v2[i]);
}
}

int main()
{
vector target, arr;

int res;
{Solution slu;target = { 5, 1, 3 }, arr = { 9, 4, 2, 3, 4 };res = slu.minOperations(target, arr);Assert(2, res);
}
{Solution slu;target = { 6,4,8,1,3,2 }, arr = { 4,7,6,2,3,8,6,1 };res = slu.minOperations(target, arr);Assert(3, res);
}//CConsole::Out(res);

}

2023年3月舊版

class Solution {
public:
int minOperations(vector& target, vector& arr) {
std::unordered_map<int, int> mValueToIndex;
for (int i = 0; i < target.size(); i++)
{
mValueToIndex[target[i]] = i+1;
}
for (const auto& a : arr)
{
if (mValueToIndex.count(a))
{
m_arr.push_back(mValueToIndex[a]);
}
}
Do();
return target.size() - m_iMaxPublicNum;
}
void Do()
{
std::map<int, int> mValueNum;
for (const auto& a : m_arr)
{
auto it = mValueNum.lower_bound(a);
int iNum = 1;
if (mValueNum.begin() != it)
{
auto tmp = it;
iNum = (–tmp)->second + 1;
}
if (mValueNum.end() != it)
{
if (iNum >= it->second)
{
mValueNum.erase(it);
}
}
m_iMaxPublicNum = max(m_iMaxPublicNum, iNum);
mValueNum[a] = iNum;
}
}
vector m_arr;
int m_iMaxPublicNum=0;//最大公共系列
};

擴展閱讀

視頻課程

有效學習:明確的目標 及時的反饋 拉伸區(難度合適),可以先學簡單的課程,請移步CSDN學院,聽白銀講師(也就是鄙人)的講解。
https://edu.csdn.net/course/detail/38771

如何你想快

速形成戰斗了,為老板分憂,請學習C#入職培訓、C++入職培訓等課程
https://edu.csdn.net/lecturer/6176

相關下載

想高屋建瓴的學習算法,請下載《喜缺全書算法冊》doc版
https://download.csdn.net/download/he_zhidan/88348653

我想對大家說的話
聞缺陷則喜是一個美好的愿望,早發現問題,早修改問題,給老板節約錢。
子墨子言之:事無終始,無務多業。也就是我們常說的專業的人做專業的事。
如果程序是一條龍,那算法就是他的是睛

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/161960.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/161960.shtml
英文地址,請注明出處:http://en.pswp.cn/news/161960.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【如何學習Python自動化測試】—— 多層窗口定位

6 、 多層窗口定位 多層窗口指的是在操作系統圖形界面中&#xff0c;一個窗口被另一個窗口覆蓋的情況。在多層窗口中&#xff0c;如何定位需要操作的窗口&#xff1f; 一種常見的方法是使用操作系統提供的AltTab快捷鍵&#xff0c;可以在打開的所有窗口中快速切換焦點。如果需要…

第十三章 控制值的轉換 - 處理UTC時區指示符

文章目錄 第十三章 控制值的轉換 - 處理UTC時區指示符 第十三章 控制值的轉換 - 處理UTC時區指示符 對于支持XML的類&#xff0c;可以指定在從XML文檔導入時是否使用UTC時區指示符。同樣&#xff0c;可以指定是否在導出時包含UTC時區指示符。 為此&#xff0c;指定XMLTIMEZON…

GEE生物量碳儲量——利用sens和MK檢驗方法計算1987-2022年森林地上生物量AGB和碳儲量的時空變化特征

簡介: 本文是將之前已經處理好的森林生物量和碳儲量數據保存到GEE Assets中,然后分別將單張影像導入到代碼編輯器中,構建一個時間序列集合,并且這里需要用到的是我們給影像添加指定的時間屬性,這樣方便進行下一步的時序分析和空間預測。 首先,需要收集1987年至2022年期…

C語言實現Linux下TCP Server測試工具

Linux TCP Server測試工具代碼 實現了接受數據并輸出文本和十六制字符串 #include <stdio.h> #include<string.h> #include <unistd.h> #include <stdlib.h> #include <errno.h> #include <signal.h> #include <arpa/inet.h> #incl…

STM32內存介紹

ROM是一種只讀存儲器&#xff0c;經歷了從NOR Flash到NAND Flash再到現在的eMMC的發展。為了便于使用和大批量生產&#xff0c;ROM進一步分為了4種類型&#xff1a;PROM、EPROM、EEPROM和Flash。PROM只能被編程一次&#xff0c;EPROM可擦寫可編程且可達1000次&#xff0c;EEPRO…

leetcode/hot100

文章目錄 一、哈希1.兩數之和2.字母異位詞分組3.最長連續序列 二、雙指針4. 移動零5.盛最多水的容器6.三數之和7.接雨水 三、滑動窗口8.無重復字符的最長子串9.找到字符串中所有字母異位詞 四、子串10.和為 K 的子數組 一、哈希 1.兩數之和 1. 兩數之和 class Solution { pu…

規則引擎Drools使用,0基礎入門規則引擎Drools(二)高級語法

文章目錄 系列文章索引五、規則屬性1、enabled屬性2、dialect屬性3、salience屬性4、no-loop屬性5、activation-group屬性6、agenda-group屬性7、auto-focus屬性8、timer屬性9、date-effective屬性10、date-expires屬性 六、Drools高級語法1、global全局變量2、query查詢3、fun…

20231122給RK3399的挖掘機開發板適配Android12

20231122給RK3399的挖掘機開發板適配Android12 2023/11/22 9:30 主要步驟&#xff1a; rootrootrootroot-X99-Turbo:~$ tar --use-compress-programpigz -xvpf rk356x_android12_220722.tgz rootrootrootroot-X99-Turbo:~$ cd rk_android12_220722/ rootrootrootroot-X99-Tur…

rk3568 適配以太網(mac 2 mac)

rk3568 適配以太網(mac 2 mac) MDI(Media Dependent Interface)是以太網中的一種接口標準,用于連接物理層(PHY)和數據鏈路層(MAC)之間的傳輸介質。 在以太網中,MDI通常通過RJ-45插座來實現,用于連接網線和網絡設備。MDI接口提供了電氣和機械特性,使得PHY和MAC能夠正…

Python通過串口收發文件

單位內外網是隔離的,USB對拷線被禁用,安全優盤使用太費事,就想到了通過串口傳輸文件. import serial from xmodem import XMODEM import osdef Send_File(filepath, portCOM8, baudrate115200):bn os.path.basename(filepath)filesize os.stat(filepath).st_sizestrSendFile…

帶記憶的超級GPT智能體,能做飯、煮咖啡、整理家務!

隨著AI技術的快速迭代&#xff0c;Alexa、Siri、小度、天貓精靈等語音助手得到了廣泛應用。但在自然語言理解和完成復雜任務方面仍然有限。 相比文本的標準格式&#xff0c;語音充滿復雜性和多樣性&#xff08;例如&#xff0c;地方話&#xff09;,傳統方法很難適應不同用戶的…

【每日OJ —— 20.有效的括號(棧)】

每日OJ —— 20.有效的括號&#xff08;棧&#xff09; 1.題目&#xff1a;20.有效的括號&#xff08;棧&#xff09;2.方法講解2.1.解法2.1.1.算法講解2.1.2.代碼實現2.1.3.提交通過展示 1.題目&#xff1a;20.有效的括號&#xff08;棧&#xff09; 2.方法講解 2.1.解法 利用…

2023 年 亞太賽 APMCM (B題)國際大學生數學建模挑戰賽 |數學建模完整代碼+建模過程全解全析

當大家面臨著復雜的數學建模問題時&#xff0c;你是否曾經感到茫然無措&#xff1f;作為2022年美國大學生數學建模比賽的O獎得主&#xff0c;我為大家提供了一套優秀的解題思路&#xff0c;讓你輕松應對各種難題。 問題一&#xff1a; 建立沒有作物的玻璃溫室內的溫度和風速分…

C語言二十四彈--喝汽水問題

C語言解決喝汽水問題 題目&#xff1a;喝汽水&#xff0c;1瓶汽水1元&#xff0c;2個空瓶可以換一瓶汽水&#xff0c;給20元&#xff0c;可以喝多少汽水&#xff1f; 方法一、逐瓶購買法 思路&#xff1a;一瓶瓶的買 當空瓶有兩個時&#xff0c;汽水數加1即可。 #include &…

MacOS 成為惡意軟件活動的目標

Malwarebytes 警告稱&#xff0c;一個針對 Mac 操作系統 (OS) 的數據竊取程序正在通過虛假的網絡瀏覽器更新分發給毫無戒心的目標。 Atomic Stealer&#xff0c;也稱為 AMOS&#xff0c;是 Mac OS 上流行的竊取程序。 Atomic Stealer (AMOS) 惡意軟件最近被發現使用“ClearFa…

ImportError: cannot import name ‘contextfilter‘ from ‘jinja2‘解決方案

大家好,我是愛編程的喵喵。雙985碩士畢業,現擔任全棧工程師一職,熱衷于將數據思維應用到工作與生活中。從事機器學習以及相關的前后端開發工作。曾在阿里云、科大訊飛、CCF等比賽獲得多次Top名次。現為CSDN博客專家、人工智能領域優質創作者。喜歡通過博客創作的方式對所學的…

匯編-pop出棧指令

32位匯編 執行動作分為兩步&#xff1a; 第一步&#xff1a;讀出數據 第二步&#xff1a;改變棧地址 如果操作數是16位&#xff0c; 則ESP加2&#xff1b; 如果操作數是32位&#xff0c; 則ESP加4 espesp2 或 espesp4 格式&#xff1a;

九、sdl顯示bmp圖片

前言 SDL中內置加載BMP的API&#xff0c;使用起來會更加簡單&#xff0c;便于初學者學習使用SDL 如果需要加載JPG、PNG等其他格式的圖片&#xff0c;可以使用第三方庫&#xff1a;SDL_image 測試環境&#xff1a; ffmpeg的4.3.2自行編譯版本windows環境qt5.12sdl2.0.22&…

力扣第462題 最小操作次數使數組元素相等 II C++ 排序基礎 附Java代碼

題目 462. 最小操作次數使數組元素相等 II 中等 相關標簽 數組 數學 排序 給你一個長度為 n 的整數數組 nums &#xff0c;返回使所有數組元素相等需要的最小操作數。 在一次操作中&#xff0c;你可以使數組中的一個元素加 1 或者減 1 。 示例 1&#xff1a; 輸入&a…

Python深入分享之閉包

閉包(closure)是函數式編程的重要的語法結構。函數式編程是一種編程范式 (而面向過程編程和面向對象編程也都是編程范式)。在面向過程編程中&#xff0c;我們見到過函數(function)&#xff1b;在面向對象編程中&#xff0c;我們見過對象(object)。函數和對象的根本目的是以某種…