【深度優先搜索】【樹】【C++算法】2003. 每棵子樹內缺失的最小基因值

作者推薦

動態規劃的時間復雜度優化

本文涉及知識點

深度優先搜索

LeetCode2003. 每棵子樹內缺失的最小基因值

有一棵根節點為 0 的 家族樹 ,總共包含 n 個節點,節點編號為 0 到 n - 1 。給你一個下標從 0 開始的整數數組 parents ,其中 parents[i] 是節點 i 的父節點。由于節點 0 是 根 ,所以 parents[0] == -1 。
總共有 105 個基因值,每個基因值都用 閉區間 [1, 105] 中的一個整數表示。給你一個下標從 0 開始的整數數組 nums ,其中 nums[i] 是節點 i 的基因值,且基因值 互不相同 。
請你返回一個數組 ans ,長度為 n ,其中 ans[i] 是以節點 i 為根的子樹內 缺失 的 最小 基因值。
節點 x 為根的 子樹 包含節點 x 和它所有的 后代 節點。
示例 1:
在這里插入圖片描述

輸入:parents = [-1,0,0,2], nums = [1,2,3,4]
輸出:[5,1,1,1]
解釋:每個子樹答案計算結果如下:

  • 0:子樹包含節點 [0,1,2,3] ,基因值分別為 [1,2,3,4] 。5 是缺失的最小基因值。
  • 1:子樹只包含節點 1 ,基因值為 2 。1 是缺失的最小基因值。
  • 2:子樹包含節點 [2,3] ,基因值分別為 [3,4] 。1 是缺失的最小基因值。
  • 3:子樹只包含節點 3 ,基因值為 4 。1是缺失的最小基因值。
    示例 2:
    在這里插入圖片描述

輸入:parents = [-1,0,1,0,3,3], nums = [5,4,6,2,1,3]
輸出:[7,1,1,4,2,1]
解釋:每個子樹答案計算結果如下:

  • 0:子樹內包含節點 [0,1,2,3,4,5] ,基因值分別為 [5,4,6,2,1,3] 。7 是缺失的最小基因值。
  • 1:子樹內包含節點 [1,2] ,基因值分別為 [4,6] 。 1 是缺失的最小基因值。
  • 2:子樹內只包含節點 2 ,基因值為 6 。1 是缺失的最小基因值。
  • 3:子樹內包含節點 [3,4,5] ,基因值分別為 [2,1,3] 。4 是缺失的最小基因值。
  • 4:子樹內只包含節點 4 ,基因值為 1 。2 是缺失的最小基因值。
  • 5:子樹內只包含節點 5 ,基因值為 3 。1 是缺失的最小基因值。
    示例 3:

輸入:parents = [-1,2,3,0,2,4,1], nums = [2,3,4,5,6,7,8]
輸出:[1,1,1,1,1,1,1]
解釋:所有子樹都缺失基因值 1 。

提示:
n == parents.length == nums.length
2 <= n <= 105
對于 i != 0 ,滿足 0 <= parents[i] <= n - 1
parents[0] == -1
parents 表示一棵合法的樹。
1 <= nums[i] <= 105
nums[i] 互不相同。

深度優先搜索

除了基因1的節點及它的祖先,其它節點都缺少1。
DFS(cur)結束時,處理了且只處理了它哥哥及自己的后代,如果我們將基因1及其祖先調整成長子。可以將空間復雜從O(nlogn)降低到O(n)。
注意:如果不優化,空間復雜度是O(nn),就是直接為每個節點分配空間,復制所有的后代。極端情況下,獨子樹的空間復雜度是O(nn)。直接用子樹的空間,獨子樹空間復雜度O(n);非獨子樹O(nlong)。

超時代碼

class CParentToNeiBo
{
public:CParentToNeiBo(const vector<int>& parents){m_vNeiBo.resize(parents.size());for (int i = 0; i < parents.size(); i++){if (-1 == parents[i]){m_root = i;}else{m_vNeiBo[parents[i]].emplace_back(i);}}}vector<vector<int>> m_vNeiBo;int m_root=-1;
};class Solution {
public:vector<int> smallestMissingValueSubtree(vector<int>& parents, vector<int>& nums) {CParentToNeiBo neiBo(parents);m_nums = nums;m_vIs1.resize(nums.size());m_ans.assign(nums.size(),1);m_vHas.resize(100'000+10);DFS1(neiBo.m_root, neiBo.m_vNeiBo);for (auto& v : neiBo.m_vNeiBo){for (int j = 1; j < v.size(); j++){if (m_vIs1[v[j]]){std::swap(v[0], v[j]);}}}DFS2(neiBo.m_root, neiBo.m_vNeiBo);return m_ans;}void DFS2(int cur, vector<vector<int>>& neiBo){		for (const auto& next : neiBo[cur]){DFS2(next, neiBo);}m_vHas[m_nums[cur]] = true;while (m_vHas[m_iNeed]){m_iNeed++;}if (m_vIs1[cur]){m_ans[cur] = m_iNeed;}}bool DFS1(int cur, vector<vector<int>>& neiBo){bool b = (1 == m_nums[cur]);		for (const auto& next : neiBo[cur]){b |= DFS1(next, neiBo);}return m_vIs1[cur]=b;}vector<int> m_nums,m_ans;vector<bool> m_vIs1;int m_iNeed = 1;vector<bool> m_vHas;
};

1及其祖先不用DFS

class CParentToNeiBo
{
public:CParentToNeiBo(const vector<int>& parents){m_vNeiBo.resize(parents.size());for (int i = 0; i < parents.size(); i++){if (-1 == parents[i]){m_root = i;}else{m_vNeiBo[parents[i]].emplace_back(i);}}}vector<vector<int>> m_vNeiBo;int m_root=-1;
};class Solution {
public:vector<int> smallestMissingValueSubtree(vector<int>& parents, vector<int>& nums) {CParentToNeiBo neiBo(parents);m_nums = nums;m_vIs1.resize(nums.size());m_ans.assign(nums.size(),1);m_vHas.resize(100'000+10);int i1 = std::find(nums.begin(), nums.end(), 1)- nums.begin();while ((-1 != i1) && (nums.size() != i1)){m_vIs1[i1] = true;i1 = parents[i1];}for (auto& v : neiBo.m_vNeiBo){for (int j = 1; j < v.size(); j++){if (m_vIs1[v[j]]){std::swap(v[0], v[j]);}}}DFS2(neiBo.m_root, neiBo.m_vNeiBo);return m_ans;}void DFS2(int cur, vector<vector<int>>& neiBo){		for (const auto& next : neiBo[cur]){DFS2(next, neiBo);}m_vHas[m_nums[cur]] = true;		if (m_vIs1[cur]){while (m_vHas[m_iNeed]){m_iNeed++;}m_ans[cur] = m_iNeed;}}vector<int> m_nums,m_ans;vector<bool> m_vIs1;int m_iNeed = 1;vector<bool> m_vHas;
};

測試用例


template<class T,class T2>
void Assert(const T& t1, const T2& t2)
{assert(t1 == t2);
}template<class T>
void Assert(const vector<T>& v1, const vector<T>& 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<int> parents,  nums;{Solution sln;parents = { -1, 0, 0, 2 }, nums = { 1, 2, 3, 4 };auto res = sln.smallestMissingValueSubtree(parents, nums);Assert({ 5,1,1,1 }, res);}{Solution sln;parents = { -1, 0, 1, 0, 3, 3 }, nums = { 5, 4, 6, 2, 1, 3 };auto res = sln.smallestMissingValueSubtree(parents, nums);Assert({ 7,1,1,4,2,1 }, res);}{Solution sln;parents = { -1, 2, 3, 0, 2, 4, 1 }, nums = { 2, 3, 4, 5, 6, 7, 8 };auto res = sln.smallestMissingValueSubtree(parents, nums);Assert({ 1,1,1,1,1,1,1 }, res);}
}

2023年2月版(當時能過)

class Solution {
public:
vector smallestMissingValueSubtree(const vector& parents, const vector& nums) {
m_c = nums.size();
m_vDirect.resize(m_c);
for (int i = 1; i < parents.size(); i++)
{
m_vDirect[parents[i]].push_back(i);
}
m_vVisiteValue.resize(m_c + 1);
m_vRet.assign(m_c, 1);
for (int i = 0; i < nums.size(); i++)
{
if (1 == nums[i])
{
DFS(i, -1,parents, nums);
break;
}
}
return m_vRet;
}
void DFS(int iCur, int iFromChild,const vector& parents, const vector& nums)
{
if (-1 == iCur)
{
return;
}
DFSForValue(iCur, iFromChild, nums);
int iMiss = (-1 == iFromChild) ? 1 : m_vRet[iFromChild];
while ((iMiss < m_vVisiteValue.size()) && (m_vVisiteValue[iMiss]))
{
iMiss++;
}
m_vRet[iCur] = iMiss;
DFS(parents[iCur], iCur, parents, nums);
}
void DFSForValue(int iCur, int iFromChild, const vector& nums)
{
m_vVisiteValue[nums[iCur]] = true;
for (auto& next : m_vDirect[iCur])
{
if (next == iFromChild)
{
continue;
}
DFSForValue(next, iFromChild, nums);
}
}
int m_c;
vector<vector> m_vDirect;
vector m_vRet;
vector m_vVisiteValue;
};

擴展閱讀

視頻課程

有效學習:明確的目標 及時的反饋 拉伸區(難度合適),可以先學簡單的課程,請移步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

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

測試環境

操作系統:win7 開發環境: VS2019 C++17
或者 操作系統:win10 開發環境: VS2022 C++17
如無特殊說明,本算法用**C++**實現。

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

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

相關文章

第二講:用geth和以太坊交互

一&#xff1a;安裝geth brew install ethereum geth github網址&#xff1a; https://github.com/ethereum/go-ethereum 二&#xff1a; 用geth連接以太坊 以太坊有主網絡&#xff08;Ethereum Mainnet&#xff09;&#xff0c;有測試網絡&#xff08;Sepolia、Goerli 等等…

設計模式學習筆記 - 設計原則 - 5.依賴反轉原則(控制反轉、依賴反轉、依賴注入)

前言 今天學習 SOLID 中的最后一個原則&#xff0c;依賴反轉原則。 本章內容&#xff0c;可以帶著如下幾個問題&#xff1a; “依賴反轉” 這個概念指的是 “誰跟誰” 的 “什么依賴” 被反轉了&#xff1f; “反轉” 這兩個字該如何理解。我們還經常聽到另外兩個概念&#…

【分塊三維重建】【slam】LocalRF:逐步優化的局部輻射場魯棒視圖合成(CVPR 2023)

項目地址&#xff1a;https://localrf.github.io/ 題目&#xff1a;Progressively Optimized Local Radiance Fields for Robust View Synthesis 來源&#xff1a;KAIST、National Taiwan University、Meta 、University of Maryland, College Park 提示&#xff1a;文章用了s…

【Spring】20 解析Spring注解驅動的容器配置

文章目錄 注解 vs. XMLJavaConfig選項注解配置注解注入順序注解處理器實際運用總結 Spring 框架一直以 XML 配置為主導&#xff0c;然而隨著注解驅動配置的引入&#xff0c;我們不禁思考&#xff1a;是注解配置優于 XML 呢&#xff0c;還是反之&#xff1f;本篇博客將介紹 Spri…

如何將一個遠程git的所有分支推到另一個遠程分支上

如何將一個遠程git的所有分支推到另一個遠程分支上 最初有 12 個分支 執行 git remote add 遠程名 遠程git地址 git push 遠程名 --tags "refs/remotes/origin/*:refs/heads/*"之后就變成 26個分支

小項目:2024/3/2

一、TCP機械臂測試 代碼&#xff1a; #include <myhead.h> #define SER_IP "192.168.125.254" //服務器端IP #define SER_PORT 8888 //服務器端端口號#define CLI_IP "192.168.199.131" //客戶端IP #define CLI_P…

100條數據秒殺,如何避免超賣【待補充更細的資料】

使用Redis預減庫存&#xff1a;利用Redis的原子性操作&#xff0c;如DECR命令&#xff0c;來預先減少庫存。當商品庫存數量在Redis中被減少到0時&#xff0c;后續的請求將被拒絕&#xff0c;從而確保只有限定數量的訂單能夠進入后續流程。悲觀鎖&#xff1a;在數據庫層面使用悲…

面試筆記系列八之JVM基礎知識點整理及常見面試題

目錄 類實例化加載順序 類的實例化順序 JVM創建對象的過程 JVM的運行機制 直接內存&#xff08;Direct Memory&#xff09; JVM后臺運行的線程 JVM 常用參數 標準參數中比較有用的&#xff1a; 非標準參數又稱為擴展參數&#xff0c;比較有用的是 非Stable參數 class初…

【DAY07 軟考中級備考筆記】數據結構:線性結構,數組矩陣和廣義表

數據結構&#xff1a;線性結構&#xff0c;數組矩陣和廣義表 3月2日 – 天氣&#xff1a;晴 1. 線性表的定義和存儲方式 > 這一部分只需要掌握下面的兩點即可&#xff1a; > > * 采用順序存儲和鏈式存儲的特點 > * 單鏈表的插入和刪除操作 2. 棧和隊列 > 這里需…

35 Spring整合Elasticsearch

文章目錄 Spring整合Elasticsearch引入依賴配置Elasticsearch解決沖突 使用ElasticsearchSpring Data Elasticsearch建立映射關系常用方法添加數據修改數據刪除數據搜索數據&#xff08;es核心&#xff09;步驟構造搜索條件 并 應用進行查詢使用查詢結果 Spring整合Elasticsear…

Spring注解之事務 @Transactional

目錄 Spring 對事務的支持 事務 Transactional Spring 對事務的支持 提醒一次&#xff1a;你的程序是否支持事務首先取決于數據庫 &#xff0c;比如使用 MySQL 的話&#xff0c;如果你選擇的是 innodb 引擎&#xff0c;那么恭喜你&#xff0c;是可以支持事務的。但是&#x…

鴻蒙Harmony應用開發—ArkTS聲明式開發(通用屬性:Popup控制)

給組件綁定popup彈窗&#xff0c;并設置彈窗內容&#xff0c;交互邏輯和顯示狀態。 說明&#xff1a; 從API Version 7開始支持。后續版本如有新增內容&#xff0c;則采用上角標單獨標記該內容的起始版本。 popup彈窗的顯示狀態在onStateChange事件回調中反饋&#xff0c;其顯…

opencv內存溢出del釋放變量 (python)

報錯&#xff1a; cv2.error: OpenCV(3.4.17) D:\a\opencv-python\opencv-python\opencv\modules\core\src\alloc.cpp:73: error: (-4:Insufficient memory) Failed to allocate 12211548 bytes in function ‘cv::OutOfMemoryError’ 檢查內存代碼 import psutil# 獲取當前進…

內存空間擔保機制

什么是內存空間擔保機制&#xff1f; 內存空間擔保機制&#xff08;Memory Space Guarantee&#xff09;是垃圾回收&#xff08;Garbage Collection&#xff09;算法中的一種策略。它用于在進行垃圾回收過程&#xff08;如Minor GC或Full GC&#xff09;時&#xff0c;確保老年…

Java項目layui分頁中文亂碼

【問題描述】這部分沒改之前中文亂碼。 【解決辦法】在layui.js或者layui.all.js文件中替換共、頁、條轉換成Unicode碼格式。 字符Unicode共&#x5171頁&#x9875條&#x6761【完美解決】改完之后重新運行項目&#xff0c;瀏覽器F12緩存清除就好了&#xff0c;右鍵

MySQL的單表和多表查詢

我們在前面曾構建過三個用于實驗的表格&#xff0c;下面將基于這三個表進行實踐。 # 建立一個用于實驗的三個表格 mysql> create table emp (-> empno varchar(10),-> ename varchar(50),-> job varchar(50),-> mgr int,-> hiredate timestamp,-&…

課程表系列(BFS)

廣度優先搜索 文章目錄 廣度優先搜索207. 課程表210. 課程表 II思路 630. 課程表 III1462. 課程表 IV547. 省份數量 207. 課程表 207. 課程表 你這個學期必須選修 numCourses 門課程&#xff0c;記為 0 到 numCourses - 1 。 在選修某些課程之前需要一些先修課程。 先修課程…

c++11 標準模板(STL)(std::tuple)(三)

定義于頭文件 <tuple> template< class... Types > class tuple; (C11 起) 類模板 std::tuple 是固定大小的異類值匯集。它是 std::pair 的推廣。 若 (std::is_trivially_destructible_v<Types> && ...) 為 true &#xff0c;則 tuple 的析構函數是…

【AI繪畫】免費GPU Tesla A100 32G算力部署Stable Diffusion

免責聲明 在閱讀和實踐本文提供的內容之前&#xff0c;請注意以下免責聲明&#xff1a; 侵權問題: 本文提供的信息僅供學習參考&#xff0c;不用做任何商業用途&#xff0c;如造成侵權&#xff0c;請私信我&#xff0c;我會立即刪除&#xff0c;作者不對讀者因使用本文所述方法…

Matlab 機器人工具箱 RobotArm類

文章目錄 1 RobotArm1.1 方法1.2 注意2 RobotArm.RobotArm3 RobotArm.cmove4 其他官網:Robotics Toolbox - Peter Corke 1 RobotArm 串聯機械臂類 1.1 方法 方法描述plot顯示機器人的圖形表示teach驅動物理和圖形機器人mirror使用機器人作為從機來驅動圖形</