劍指offer刷題記錄Day2 07.數組中重復的數字 ---> 11.旋轉數組的最小數字

名人說:莫道桑榆晚,為霞尚滿天。——劉禹錫(劉夢得,詩豪)
創作者:Code_流蘇(CSDN)(一個喜歡古詩詞和編程的Coder😊)

目錄

        • 1、重建二叉樹
          • ①代碼實現(帶注釋)
          • ②補充說明(前序遍歷和中序遍歷重建二叉樹的原理)
        • 2、二叉樹的下一個結點
          • ①代碼實現(帶注釋)
        • 3、用兩個棧實現隊列
          • ①代碼實現(帶注釋)
          • ②補充說明(棧和隊列)
        • 4、斐波那契數列
          • ①代碼實現(帶注釋)
          • ②補充說明(斐波那契數列)
        • 5、旋轉數組的最小數字
          • ①代碼實現(帶注釋)
          • ②補充說明(二分搜索法)

1、重建二叉樹

原題鏈接:07.重建二叉樹

在這里插入圖片描述

①代碼實現(帶注釋)
#include <unordered_map>
#include <vector>
/*** struct TreeNode {*  int val;*  struct TreeNode *left;*  struct TreeNode *right;*  TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}* };*/
/*解題關鍵:前序序列中的第一個元素總是樹的根。
通過這個根,我們可以在中序序列中找到根的索引位置。中序序列又總是被根索引分成兩部分:左子樹和右子樹。
同樣地,我們就能夠可以確定前序序列中左右子樹的邊界。最后通過遞歸這個過程來重建整棵樹即可解決問題。*/class Solution {public:unordered_map<int, int>indexMap; // 用于快速訪問中序遍歷中值的索引的映射TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder,int preorderStart, int preorderEnd, int inorderStart, int inorderEnd) {//若前序遍歷的起始位置大于結束位置               if (preorderStart > preorderEnd) {return nullptr; //若返回 nullptr ,表示該子樹不存在任何節點。}// 根據前序遍歷的特點,我們可以從前序遍歷獲取根節點值int rootVal = preorder[preorderStart]; // 創建原二叉樹的根節點TreeNode* root = new TreeNode(rootVal); // 在中序遍歷中找到根的索引下標int rootIndexInInorder = indexMap[rootVal]; // leftElements:左子樹中的元素數量int leftElements = rootIndexInInorder - inorderStart;// 遞歸構建左子樹root->left = buildTree(preorder, inorder, preorderStart + 1,preorderStart + leftElements, inorderStart, rootIndexInInorder - 1);// 遞歸構建右子樹root->right = buildTree(preorder, inorder, preorderStart + leftElements + 1,preorderEnd, rootIndexInInorder + 1, inorderEnd);//返回每次所構建子樹的根節點return root;}TreeNode* reConstructBinaryTree(vector<int>& preOrder, vector<int>& vinOrder) {int n = preOrder.size();// 填充indexMap以便快速訪問中序遍歷中的索引/*在重建二叉樹的過程中,需要頻繁地找到前序遍歷中的根節點在中序遍歷序列中的位置,這樣才能確定左右子樹的范圍,因此此處使用了映射。如果不使用映射,每次查找都可能需要遍歷整個中序遍歷序列來找到根節點的位置*/for (int i = 0; i < n; i++) {indexMap[vinOrder[i]] = i;}return buildTree(preOrder, vinOrder, 0, n - 1, 0, n - 1);}
};

在這里插入圖片描述

②補充說明(前序遍歷和中序遍歷重建二叉樹的原理)

該題根據前序遍歷和中序遍歷重建二叉樹的原理是什么?

構建二叉樹的原理依賴于前序遍歷和中序遍歷的特性來確定樹的結構。前序遍歷的順序是根 左 右。中序遍歷的順序是左 根 右。

根據前序遍歷和中序遍歷構建二叉樹的步驟:

  1. 確定根節點:在前序遍歷中,序列的第一個元素總是樹的根節點。

  2. 劃分左右子樹:在中序遍歷中,根節點將序列分為兩部分,左邊是樹的左子樹,右邊是樹的右子樹。

  3. 遞歸構建:利用上一步得到的左右子樹的中序遍歷序列,和從前序遍歷序列中提取相應的左右子樹序列,遞歸地重復上述過程構建整棵樹。

例如,假設有一棵樹的前序遍歷序列是 [ A , B , D , E , C , F ] [\text{A}, \text{B}, \text{D}, \text{E}, \text{C}, \text{F}] [A,B,D,E,C,F],中序遍歷序列是 [ D , B , E , A , C , F ] [\text{D}, \text{B}, \text{E}, \text{A}, \text{C}, \text{F}] [D,B,E,A,C,F]

  1. 前序遍歷的第一個元素是 A A A,所以 A A A 是根節點。

  2. 在中序遍歷中, A A A 前面的 [ D , B , E ] [\text{D}, \text{B}, \text{E}] [D,B,E] 是左子樹的中序遍歷序列, A A A 后面的 [ C , F ] [\text{C}, \text{F}] [C,F] 是右子樹的中序遍歷序列。

  3. 遞歸構建左子樹和右子樹。

    • 對于左子樹,前序遍歷序列變為 [ B , D , E ] [\text{B}, \text{D}, \text{E}] [B,D,E],中序遍歷序列是 [ D , B , E ] [\text{D}, \text{B}, \text{E}] [D,B,E]。重復上述步驟,可以構建出左子樹。
    • 對于右子樹,前序遍歷序列是 [ C , F ] [\text{C}, \text{F}] [C,F],中序遍歷序列是 [ C , F ] [\text{C}, \text{F}] [C,F]。重復上述步驟,可以構建出右子樹。

通過這種方式,我們就可以準確地重建原始的二叉樹結構了。

2、二叉樹的下一個結點

原題鏈接:08.二叉樹的下一個結點

在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述

①代碼實現(帶注釋)
/*
struct TreeLinkNode {int val;struct TreeLinkNode *left;struct TreeLinkNode *right;struct TreeLinkNode *next;TreeLinkNode(int x) :val(x), left(NULL), right(NULL), next(NULL) {}
};
*/
class Solution {public:// 定義樹節點指針向量nodes 用于存儲中序遍歷所有節點指針vector<TreeLinkNode*> nodes;// 獲取給定節點的下一個節點TreeLinkNode* GetNext(TreeLinkNode* pNode) {TreeLinkNode* root = pNode;// 循環遍歷找到根節點while (root->next) root = root->next;// 對樹進行中序遍歷,并將節點指針存儲在nodes向量中InOrder(root); int n = nodes.size(); // 獲取遍歷后得到的節點總數// 遍歷節點,查找給定節點的下一個節點for (int i = 0; i < n - 1; i++) {TreeLinkNode* cur = nodes[i];// 如果當前節點是給定節點if (pNode == cur) { // 則返回下一個節點return nodes[i +1]; }}// 若給定節點沒有下一個節點,則返回NULLreturn NULL; }// 中序遍歷二叉樹void InOrder(TreeLinkNode* root) {if (root == NULL) return;InOrder(root->left); // 遍歷左子樹//push_back函數可以在Vector向量最后添加一個元素(括號中的參數為要插入的值)nodes.push_back(root); // 訪問當前節點InOrder(root->right); // 遍歷右子樹}
};

在這里插入圖片描述

3、用兩個棧實現隊列

原題鏈接:09.用兩個棧實現隊列

在這里插入圖片描述

①代碼實現(帶注釋)
class Solution
{
public://使用兩個棧實現隊列的push操作void push(int node) {stack1.push(node); //直接將元素壓入stack1}//使用兩個棧實現隊列的pop操作int pop() {//如果stack2為空,則將stack1中的所有元素轉移到stack2中if (stack2.empty()) {while (!stack1.empty()) {//將stack1的棧頂元素壓入stack2stack2.push(stack1.top());//刪除stack1的棧頂元素stack1.pop();}}//如果stack2不為空,則直接從stack2中彈出棧頂元素,即隊頭元素//獲取stack2的棧頂元素int head = stack2.top(); //刪除stack2的棧頂元素stack2.pop();//返回隊頭元素return head;}private:stack<int> stack1;//棧1用于插入操作stack<int> stack2;//棧2用于刪除操作
};

在這里插入圖片描述

②補充說明(棧和隊列)

棧(Stack)和隊列(Queue)是兩種基本的數據結構,它們在處理數據的方式上有著本質的區別:

  • 是一種后進先出的數據結構。
    最后添加進棧的元素將是第一個被移除的。想象一下一疊盤子,你只能從頂部添加或移除盤子。常見的操作包括“push”(添加一個元素到棧頂)和“pop”(移除棧頂元素)。

  • 隊列 是一種先進先出的數據結構。
    第一個添加進隊列的元素將是第一個被移除的。可以想象成在銀行排隊,新來的顧客排在隊伍的末尾,而服務員從隊伍的前端開始服務顧客。常見的操作包括“enqueue”(將一個元素添加到隊列末尾)和“dequeue”(移除隊列前端的元素)。

4、斐波那契數列

原題鏈接:10. 斐波那契數列
在這里插入圖片描述

①代碼實現(帶注釋)
class Solution {
public:/*** 代碼中的類名、方法名、參數名已經指定,請勿修改,直接返回方法規定的值即可** * @param n int整型 * @return int整型*/int Fibonacci(int n) {//處理邊界情況if(n <= 1)return n;//初始化前兩個斐波那契數	int a=0,b=1;//計算第n項for(int i = 2; i <= n; i++){//更新斐波那契數到第n項int next = a+b;a = b;b = next;}//第n項的斐波那契數列return b;}
};

在這里插入圖片描述

②補充說明(斐波那契數列)

斐波那契數列是一種在數學和計算機科學中廣泛應用的數列。它由以下遞歸關系定義:每個數是前兩個數的和,其最初兩個數通常定義為 F ( 0 ) = 0 , F ( 1 ) = 1 F(0) = 0, F(1) = 1 F(0)=0,F(1)=1。因此,斐波那契數列的開始部分是:

0 , 1 , 1 , 2 , 3 , 5 , 8 , 13 , 21 , 34 , … 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, \ldots 0,1,1,2,3,5,8,13,21,34,

形式上,斐波那契數列可以用數學公式表示為:

F ( n ) = F ( n ? 1 ) + F ( n ? 2 ) F(n) = F(n-1) + F(n-2) F(n)=F(n?1)+F(n?2)

其中, n ≥ 2 n \geq 2 n2 F ( 0 ) = 0 F(0) = 0 F(0)=0, F ( 1 ) = 1 F(1) = 1 F(1)=1

特點:除了最開始的兩個數字外,每個數字都是其前兩個數字的和。

5、旋轉數組的最小數字

原題鏈接:11. 旋轉數組的最小數字

在這里插入圖片描述

①代碼實現(帶注釋)
class Solution {
public:/*** 代碼中的類名、方法名、參數名已經指定,請勿修改,直接返回方法規定的值即可** * @param nums int整型vector * @return int整型*//*由于數組原本是非降序排列的,旋轉后,數組被分成兩個非降序的子數組。最小值是這兩個子數組的分界點。 因此我們可以使用二分搜索法/折半查找法來優化搜索過程,這樣時間復雜度就是O(logn)。*/ int minNumberInRotateArray(vector<int>& nums) {//如果數組為空,返回-1if(nums.empty()) return -1; //定義左側left位置為0int left = 0;//右側right位置為n-1int right = nums.size() - 1;//如果旋轉數組沒有旋轉(例如[1,2,3,4,5]變成[1,2,3,4,5]),直接返回第一個元素if(nums[left] < nums[right]){return nums[left];}//二分查找while (left < right) {int mid = left + (right - left) / 2;if(nums[mid] > nums[right]){//[mid+1,right]區間left = mid + 1;}else if (nums[mid] < nums[right]) {//[left,mid]區間right = mid;}else {//當中間值和右邊值相等時,縮小范圍right--;}}//循環結束,此時left == right,指向的就是數組中的最小值return nums[left];}
};

在這里插入圖片描述

②補充說明(二分搜索法)

二分搜索法(Binary Search)是一種在有序數組中查找特定元素的高效算法。

原理:將待搜索的數組分成兩半,然后根據中間元素與目標值的比較結果來確定下一步搜索的區域,從而逐步縮小搜索范圍,直到找到目標值或確定目標值不存在。

二分搜索的基本步驟如下:

  1. 確定搜索區間:初始搜索區間為整個數組。
  2. 找到中間元素:計算搜索區間的中點位置,取出中間元素進行比較。
  3. 比較中間元素與目標值
    • 如果中間元素正好等于目標值,則搜索成功。
    • 如果中間元素小于目標值,則將搜索區間調整為中間元素右側的子區間,繼續搜索。
    • 如果中間元素大于目標值,則將搜索區間調整為中間元素左側的子區間,繼續搜索。
  4. 重復步驟2和3,直到找到目標值或搜索區間為空(表示目標值不存在于數組中)。

二分搜索的效率較高,其時間復雜度為 O ( log ? n ) O(\log n) O(logn),其中 n n n 是數組的長度。因此本題采用二分搜索法,可以幫助我們在查找數據時節省大量的時間。

很感謝你能看到這里,如有相關疑問,還請下方評論留言。
Code_流蘇(CSDN)(一個喜歡古詩詞和編程的Coder😊)
如果大家喜歡的話,請動動手點個贊和關注吧,非常感謝你們的支持!

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

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

相關文章

【重溫設計模式】職責鏈模式及其Java示例

職責鏈模式的介紹 在開發過程中&#xff0c;我們經常會遇到這樣的問題&#xff1a;一個請求需要經過多個對象的處理&#xff0c;但是我們并不知道具體由哪個對象來處理&#xff0c;或者說&#xff0c;我們希望由接收到請求的對象自己去決定如何處理或者是將請求傳遞給下一個對…

CSS 選擇器的常見用法

這里CSS選擇器主要分為以下這幾種&#xff1a;1. 標簽選擇器 2. class選擇器 3. id選擇器 4. 復合選擇器 5. 通配符選擇器 CSS 選擇器的主要功能就是選中??指定的標簽元素. 選中了元素, 才可以設置元素的屬性. 1.標簽選擇器 <style>p{color: red;} </style> &…

表單控件上的事件

<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>光標聚焦和失焦事件</title><style type"text/css">.text{color: red;font-size: 12px;}</style> </head> <bod…

【深度學習筆記】計算機視覺——錨框

錨框 目標檢測算法通常會在輸入圖像中采樣大量的區域&#xff0c;然后判斷這些區域中是否包含我們感興趣的目標&#xff0c;并調整區域邊界從而更準確地預測目標的真實邊界框&#xff08;ground-truth bounding box&#xff09;。 不同的模型使用的區域采樣方法可能不同。 這里…

吳恩達deeplearning.ai:正則化對于偏方差的影響制定用于性能評估的基準

以下內容有任何不理解可以翻看我之前的博客哦&#xff1a;吳恩達deeplearning.ai專欄 這節我們看看正則化系數 文章目錄 以線性回歸為例交叉驗證誤差對于確定 λ \lambda λ的作用 指定用于性能評估的基準語音識別的例子 以線性回歸為例 讓我們舉一個例子&#xff1a; 模型&am…

Outlook郵箱IMAP密碼怎么填寫?賬戶設置?

Outlook郵箱IMAP密碼是什么&#xff1f;Outlook如何設置IMAP&#xff1f; 許多用戶會選擇通過IMAP協議將郵箱與各種郵件客戶端進行連接。而在設置過程中&#xff0c;填寫IMAP密碼是必不可少的一步。那么&#xff0c;Outlook郵箱的IMAP密碼應該如何填寫呢&#xff1f;接下來&am…

【Linux】深入理解ls命令

&#x1f34e;個人博客&#xff1a;個人主頁 &#x1f3c6;個人專欄&#xff1a;Linux ?? 功不唐捐&#xff0c;玉汝于成 目錄 前言 正文 基本用法 常用選項 示例 高級用法 結語 我的其他博客 前言 在 Linux 系統中&#xff0c;ls 命令是一個強大而又基礎的工具&am…

高刷顯示器 - HKC VG253KM

&#x1f525;&#x1f525; 今天來給大家揭秘一款電競神器 - HKC VG253KM 高刷電競顯示器&#xff01;這款顯示器可是有著雄鷹展翅般的設計靈感&#xff0c;背后的大鵬展翅鷹翼圖騰讓人過目難忘。那么&#xff0c;這款顯示器到底有哪些過人之處呢&#xff1f;一起來看看吧&…

【MySQL】基于Docker搭建MySQL一主二從集群

本文記錄了搭建mysql一主二從集群&#xff0c;這樣的一個集群master為可讀寫&#xff0c;slave為只讀。過程中使用了docker&#xff0c;便于快速搭建單體mysql。 1&#xff0c;準備docker docker的安裝可以參考之前基于yum安裝docker的文章[1]。 容器相關命令[2]。 查看正在…

如何系統的學習Python——Python的基本語法

學習Python的基本語法是入門的第一步&#xff0c;以下是一些常見的基本語法概念&#xff1a; 注釋&#xff1a; 用#符號來添加單行注釋&#xff0c;或使用三引號(或""")來添加多行注釋。 # 這是一個單行注釋 這是 多行 注釋 變量和數據類型&#xff1a; 變量用…

Pod和容器設計模式

為什么需要 Pod&#xff1b; Pod 的實現機制&#xff1b; 詳解容器設計模式。 一、為什么需要 Pod 容器的基本概念 現在來看第一個問題&#xff1a;為什么需要 Pod&#xff1f;我們知道 Pod 是 Kubernetes 項目里面一個非常重要的概念&#xff0c;也是非常重要的一個原子調…

144. 二叉樹的前序遍歷

給你二叉樹的根節點 root &#xff0c;返回它節點值的 前序 遍歷。 示例 1&#xff1a; 輸入&#xff1a;root [1,null,2,3] 輸出&#xff1a;[1,2,3]示例 2&#xff1a; 輸入&#xff1a;root [] 輸出&#xff1a;[]示例 3&#xff1a; 輸入&#xff1a;root [1] 輸出&am…

java方法

目錄 方法的定義 方法的命名規則 方法的調用與重載 方法調用實例 方法的重載 變量的作用域 算法中常見的方法 1&#xff1a;gcd&#xff08;求兩個整數中的最大公約數&#xff09; 2&#xff1a;lcm&#xff08;求兩個整數的最小公倍數&#xff09; 3:判斷一個整數是否…

SpringCloud(18)之Sleuth +Zipkin鏈路追蹤

一、Zipkin介紹 Zipkin是一個開放源代碼分布式的跟蹤系統&#xff0c;它可以幫助收集服務的時間數據&#xff0c;以解決微服務架構中的延遲問 題&#xff0c;包括數據的收集、存儲、查找和展現。每個服務向zipkin報告計時數據&#xff0c;zipkin會根據調用關系通 過Zipkin UI…

LeetCode: 數組中的第K個最大元素

問題描述 在未排序的數組中找到第k個最大的元素。請注意&#xff0c;你需要找的是數組排序后的第k個最大的元素&#xff0c;而不是第k個不同的元素。 解題思路 解決這個問題有多種方法&#xff0c;下面是幾種常見的解題策略&#xff1a; 排序后選擇: 將數組排序&#xff0c…

ProChat 如何接入 WebSocket

WebSocket是一種在單個TCP連接上進行全雙工通信的協議&#xff0c;允許客戶端和服務器之間進行雙向實時通信。與Server-Sent Events (SSE)類似&#xff0c;WebSocket也能實現實時數據推送&#xff0c;但其功能更為強大且靈活。 全雙工通信&#xff1a;WebSocket不僅允許服務器向…

【TestNG】(4) 重試機制與監聽器的使用

在UI自動化測試用例執行過程中&#xff0c;經常會有很多不確定的因素導致用例執行失敗&#xff0c;比如網絡原因、環境問題等&#xff0c;所以我們有必要引入重試機制&#xff08;失敗重跑&#xff09;&#xff0c;來提高測試用例成功率。 在不寫代碼的情況沒有提供可配置方式…

Mysql 慢查詢日志

查詢是否開啟慢SQL日志 show variables like %slow_query_log; 開啟慢查詢日志 set global slow_query_logON; 可以通過修改MySQL的配置my.cfg或者my.ini永久生效 slow_query_logON # 開啟慢查詢日志開關 slow_query_log_file/var/lib/mysql/alvin-slow.log # 慢查詢日志…

1.2 在卷積神經網絡中,如何計算各層感受野的大小

1.2 在卷積神經網絡中&#xff0c;如何計算各層感受野的大小 分析與解答&#xff1a; 在卷積神經網絡中&#xff0c;由于卷積的局部連接性&#xff0c;輸出特征圖上的每個節點的取值&#xff0c;是由卷積核在輸入特征圖對應位置的局部區域內進行卷積而得到的&#xff0c;因此這…

COM - IWbemClassObject對象屬性的遍歷

文章目錄 COM - IWbemClassObject對象屬性的遍歷概述筆記場景封裝好的函數bool CWmiBase::enumObjVaule(IWbemClassObject* obj, std::wstring& val)bool CWmiBase::appendVarToString(BSTR& strName, VARIANT& var, std::wstring& val)bool CWmiBase::get_var…