【數據結構】關于鏈表的面試題

一、單鏈表逆置

1、法一

思路:

通過兩個輔助指針?p和 q,在遍歷鏈表時逐個反轉指針方向。

  • p初始化為?第一個有效節點,用于遍歷原鏈表;q初始化為?NULL,用于臨時保存?p?的下一個節點。
  • plist->next?被置為?NULL,表示逆置后的鏈表初始為空(頭節點指向空)。
  • 每次迭代中:q?保存?p?的下一個節點(防止斷鏈)。

  • 將?p?的?next?指向當前逆置鏈表的頭部(plist->next)。
  • 更新頭節點的?next?指向?p,使?p?成為新鏈表的第一個節點。
  • p?移動到?q(原鏈表的下一個節點),繼續循環。
  • 終止條件
    當?p?為?NULL?時,說明原鏈表已全部遍歷完畢,逆置完成。

關鍵點說明:

頭插法:通過每次將當前節點插入頭節點之后,實現鏈表的逆置。

斷鏈處理q?臨時保存?p->next,避免修改?p->next?后丟失后續節點。

時間復雜度:O(n),僅需一次遍歷。

空間復雜度:O(1),僅使用固定數量的指針變量。

示例流程:

假設原鏈表為?1 -> 2 -> 3 -> NULL,頭節點為?H

  1. 初始:H -> 1 -> 2 -> 3p?指向?1
  2. 第一次循環后:H -> 1 -> NULLp?指向?2
  3. 第二次循環后:H -> 2 -> 1 -> NULLp?指向?3
  4. 第三次循環后:H -> 3 -> 2 -> 1 -> NULLp?為?NULL,退出循環。

代碼實現:

//逆置單鏈表
void Reverse_list(Node* plist) {assert(plist != NULL);assert(plist->next != NULL);assert(plist->next->next != NULL);Node* p = plist->next;Node* q = NULL;plist->next = NULL;while (p != NULL) {q = p->next;p->next = plist->next;plist->next = p;p = q;}
}

2、法二

思路:

  1. 指針初始化
    p初始化為第一個有效節點(plist->next),q初始化為第二個節點(p->next)。p->next被置為NULL,表示反轉后的新鏈表的尾節點。

  2. 迭代反轉

    • r保存q的下一個節點(q->next),防止斷鏈。
    • q->next指向p,完成局部反轉。
    • 指針pq分別向后移動一位,繼續處理后續節點。
    • 循環終止時,p指向原鏈表的最后一個節點,即反轉后的新鏈表頭。
  3. 更新頭節點
    plist->next = p;將頭節點的next指向反轉后的新鏈表頭。

示例流程

假設鏈表為 頭節點 -> 1 -> 2 -> 3 -> NULL

  1. 初始狀態:
    p = 1, q = 2, 1->next = NULL
  2. 第一次循環:
    r = 3, 2->next = 1, p = 2, q = 3
  3. 第二次循環:
    r = NULL, 3->next = 2, p = 3, q = NULL
  4. 結束循環,頭節點->next = 3,得到 頭節點 -> 3 -> 2 -> 1 -> NULL

關鍵點

  • 三指針協同pqr分別用于記錄當前節點、下一個節點及臨時保存節點,確保反轉過程中不斷鏈。
  • 頭節點處理:傳入的plist通常為不存儲數據的頭節點,反轉后仍需保持頭節點指向新鏈表頭。
  • 時間復雜度:O(n),僅需遍歷一次鏈表;空間復雜度O(1),僅使用固定數量的指針。

邊界情況

若鏈表為空或僅有一個節點,斷言會觸發錯誤。實際應用中需根據需求調整斷言條件或添加特殊處理。

?代碼實現:

void Reverse_list2(Node* plist) {assert(plist != NULL);assert(plist->next != NULL);assert(plist->next->next != NULL);Node* p = plist->next;Node* q = p->next;Node* r = NULL;p->next = NULL;while (q != NULL) {r = q->next;q->next = p;p = q;q = r;}plist->next = p;
}

二、如何判斷兩個單鏈表存在交點

思路:兩個鏈表的指針,分別跑到自身的尾節點,判斷是否為同一個尾節點

?代碼實現:

bool Intersect(Node* plist1, Node* plist2) {assert(plist1 != NULL);assert(plist2 != NULL);Node* p = plist1;Node* q = plist2;for (; p->next != NULL; p = p->next);for (; q->next != NULL; q = q->next);return p == q;
}

?三、獲取兩個單鏈表的相交點

思路:

該算法的目標是找到兩個單鏈表的相交節點(如果有)。核心思路是通過對齊兩個鏈表的起始位置,然后同步遍歷,直到找到相同節點。

步驟分解

  1. 檢查鏈表是否相交
    調用Intersect(plist1, plist2)函數判斷兩鏈表是否相交。若不相交,直接返回NULL

  2. 計算鏈表長度
    通過Get_Length函數獲取兩個鏈表的長度len1len2,用于后續對齊操作。

  3. 對齊起始位置
    將較長鏈表的指針p向后移動|len1 - len2|步,使得剩余未遍歷部分與較短鏈表的長度一致。此時pq(較短鏈表的頭指針)處于同一起跑線。

  4. 同步遍歷尋找交點
    同時移動pq指針,逐個節點比較。當p == q時,當前節點即為相交節點,返回該節點。

關鍵點

  • 時間復雜度:O(m+n),其中m和n為兩鏈表長度。需遍歷兩次鏈表(計算長度+同步查找)。
  • 空間復雜度:O(1),僅使用常數級額外空間。
  • 邊界條件:處理兩鏈表長度差為0時,直接進入同步遍歷階段。

示例說明

假設鏈表1為A->B->C->D,鏈表2為E->F->C->D(相交于節點C):

  1. len1=4len2=4(長度差為0,無需對齊)。
  2. 同步遍歷p(鏈表1)和q(鏈表2),第三次移動時pq均指向C,返回C

代碼實現:

Node* Get_Intersect_Node(Node* plist1, Node* plist2) {bool tag = Intersect(plist1, plist2);if (!tag) return NULL;int len1 = Get_Length(plist1);int len2 = Get_Length(plist2);Node* p = len1 >= len2 ? plist1 : plist2;Node* q = len1 >= len2 ? plist2 : plist1;//此時p指向較長的單鏈表的輔助結點,q指向較長的單鏈表的輔助結點for (int i = 0; i < abs(len1 - len2); i++) {p = p->next;}//pq同步向后走,直到相遇while (p != q) {p = p->next;q = q->next;}return p;
}

?

?

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

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

相關文章

LVS(Linux virual server)

LVS&#xff08;Linux virual server&#xff09; 系統性能擴展方式 Scale UP&#xff1a;增強單臺服務器性能&#xff0c;適合單體應用&#xff0c;但有硬件限制。 Scale Out&#xff1a;增加服務器數量&#xff0c;適合分布式和集群系統&#xff0c;可靈活擴展。 集群&#x…

在 ASP.NET Core 和 JavaScript 中配置 WebSocket

在本文中&#xff0c;我們將了解 WebSocket&#xff0c;并逐步講解如何在客戶端配置 WebSocket 并與服務器通信。首先&#xff0c;讓我們先來了解一下“ WebSocket ”。什么是 WebSocketWebSocket 是一種協議&#xff0c;它提供了一種通過持久連接在客戶端和服務器之間交換數據…

車載刷寫框架 --- 關于私有節點刷寫失敗未報引起的反思

我是穿拖鞋的漢子,魔都中堅持長期主義的汽車電子工程師。 老規矩,分享一段喜歡的文字,避免自己成為高知識低文化的工程師: 做到欲望極簡,了解自己的真實欲望,不受外在潮流的影響,不盲從,不跟風。把自己的精力全部用在自己。一是去掉多余,凡事找規律,基礎是誠信;二是…

ABP VNext + GitHub Actions:CI/CD 全流程自動化

&#x1f31f; ABP VNext GitHub Actions&#xff1a;CI/CD 全流程自動化 &#x1f4da; 目錄&#x1f31f; ABP VNext GitHub Actions&#xff1a;CI/CD 全流程自動化&#x1f929; TL;DR&#x1f504; 全局流程概覽1?? 準備工作與項目結構1.1 &#x1f6e0;? 工具鏈與 S…

Elasticsearch 重命名索引

作者&#xff1a;來自 Elastic Alex Salgado 學習如何使用四種實用方法在 Elasticsearch 中重命名索引。 想獲得 Elastic 認證&#xff1f;看看下一期 Elasticsearch Engineer 培訓什么時候開始&#xff01; Elasticsearch 擁有豐富的新功能&#xff0c;幫助你根據使用場景構建…

高通8255 Android Virtio Virtio-SPI 配置方法

目錄 一&#xff1a;VirtIO和Passthrough的區別 二&#xff1a;配置邏輯 三&#xff1a;配置方法 步驟一&#xff1a;QNX SPI資源配置 & 測試 配置 測試 步驟二&#xff1a;BE配置 &測試 配置 測試 步驟三&#xff1a;Hypervisor配置 配置 測試 步驟四&…

從零手寫紅黑樹(C++實現詳解)

目錄 一、紅黑樹概述 二、紅黑樹節點設計 (1)枚舉紅黑 &#xff08;2&#xff09;紅黑樹的節點設計 三、紅黑樹核心實現:Insert 1.首先將節點遍歷到對應位置創建對應節點并插入到二叉搜索樹對應的位置 2.本文重點的重點 &#xff08;1&#xff09;parent為黑時直接插入即…

【黃山派-SF32LB52】—硬件原理圖學習筆記

目錄 一、硬件介紹 二、芯片主控 1.模組介紹 2.原理圖介紹 3.模組供電電路 三、電源轉換部分 1.OVP過壓保護電路 2.CHG充電電路 3.系統電源橋接電路 4.LDO電路 四、Debug電路 1.一鍵下載電路 五、QSPI屏幕 六、SD卡 七、AUDIO音頻 八、GPIO電路 1.按鍵部分…

從五次方程到計算機:數學抽象如何塑造現代計算

引言 數學的發展往往始于一個具體的問題&#xff0c;而后在尋求解答的過程中&#xff0c;催生出深刻的抽象理論。從五次方程的求解到抽象代數&#xff0c;再到范疇論和λ演算&#xff0c;最終影響圖靈機和現代計算機的設計&#xff0c;這一歷程展現了數學如何從實際問題演變為通…

劇本殺小程序開發:科技賦能,重塑推理娛樂新形態

在科技飛速發展的今天&#xff0c;各個行業都在積極探索與科技的融合&#xff0c;以實現創新發展。劇本殺行業也不例外&#xff0c;劇本殺小程序的開發&#xff0c;正是科技賦能傳統娛樂的生動體現&#xff0c;它重塑了推理娛樂的新形態&#xff0c;為玩家帶來了前所未有的游戲…

機器學習sklearn入門:歸一化和標準化

bg&#xff1a;歸一化&#xff08;Normalization&#xff09;通常指將數據按比例縮放至某個特定范圍&#xff0c;但具體范圍并不一定是固定的 0到1。標準化是將數據轉換成均值為0&#xff0c;標準差為1的分布。使用場景&#xff1a;用歸一化&#xff1a;需要嚴格限定范圍&#…

【Project】kafka+flume+davinci廣告點擊實時分析系統

一、項目需求分析 某電商平臺需實現廣告實時點擊分析系統&#xff0c;核心需求為實時統計以下內容的Top10&#xff1a; 各個廣告的點擊量各個省份的廣告點擊量各個城市的廣告點擊量 通過實時掌握廣告投放效果&#xff0c;為廣告投放策略調整和大規模投入提供依據&#xff0c;以…

JAVA后端開發——success(data) vs toAjax(rows): 何時用

toAjax(int rows)用途&#xff1a;用于不返回任何數據的 “寫” 操作&#xff08;增、刪、改&#xff09;。工作原理&#xff1a;它只接收一個 int 類型的參數&#xff08;通常是數據庫操作影響的行數&#xff09;。它只關心這個數字是不是大于0&#xff0c;然后返回一個通用的…

pdf格式怎么提取其中一部分張頁?

想從PDF里提取幾個頁面&#xff0c;辦法還挺多的&#xff0c;下面給你嘮嘮常見的幾種&#xff0c;保準你一看就懂。一、用專業PDF編輯軟件提取 像Adobe Acrobat&#xff0c;這可是PDF編輯界的“老手”了。你先把要處理的PDF文件在Adobe Acrobat里打開&#xff0c;接著找到菜單欄…

Spring監聽器

1、監聽器的原理 ApplicationListener<T>是Spring框架中基于觀察者模式實現的事件監聽接口&#xff0c;用于監聽應用程序中特定類型的事件。該接口是一個函數式接口&#xff0c;從Spring 4.2開始支持Lambda表達式實現。 接口定義如下&#xff1a; FunctionalInterface …

基于Rust游戲引擎實踐(Game)

Rust游戲引擎推薦 以下是一些流行的Rust游戲引擎,適用于不同開發需求: Bevy 特點:數據驅動、模塊化設計,支持ECS架構,適合初學者和復雜項目。 適用場景:2D/3D游戲、原型開發。 Amethyst 特點:成熟的ECS框架,支持多線程,社區活躍。 適用場景:大型游戲或高性能應用。…

PyTorch 數據加載實戰:從 CSV 到圖像的全流程解析

目錄 一、PyTorch 數據加載的核心組件 1.1 Dataset 類的核心方法 1.2 DataLoader 的作用 二、加載 CSV 數據實戰 2.1 自定義 CSV 數據集 2.2 使用 TensorDataset 快速加載 三、加載圖像數據實戰 3.1 自定義圖像數據集 3.2 使用 ImageFolder 快速加載 四、加載官方數據…

程序人生,開啟2025下半年

時光匆匆&#xff0c;2025年已然過去一半。轉眼來到了7月份。 回望過去上半年&#xff0c;可能你也經歷了職場的浮沉、生活的跌宕、家庭的變故。 而下半年&#xff0c;生活依舊充滿了各種變數。 大環境的起起伏伏、生活節奏的加快&#xff0c;都讓未來的不確定性愈發凸顯。 在這…

在 .NET Core 中創建 Web Socket API

要在 ASP.NET Core 中創建 WebSocket API&#xff0c;您可以按照以下步驟操作&#xff1a;設置新的 ASP.NET Core 項目打開 Visual Studio 或您喜歡的 IDE。 創建一個新的 ASP.NET Core Web 應用程序項目。 選擇API模板&#xff0c;因為這將成為您的 WebSocket API 的基礎。在啟…

Python 之地址編碼識別

根據輸入地址&#xff0c;利用已有的地址編碼文件&#xff0c;構造處理規則策略識別地址的編碼。 lib/address.json 地址編碼文件&#xff08;這個文件太大&#xff0c;博客里放不下&#xff0c;需要的話可以到 gitcode 倉庫獲取&#xff1a;https://gitcode.com/TomorrowAndT…