數據結構:如何判斷一個鏈表中是否存在環(Check for LOOP in Linked List)

目錄

初始思考:什么叫“鏈表有環”?

? 第一種直接想法(失敗):我們是不是能“記住走過的節點”?

那我們換一個思路:我們能否只用兩個指針來檢測環?

第一步:定義兩個指針

第二步:建立循環


初始思考:什么叫“鏈表有環”?

鏈表的本質是:

Node → Node → Node → NULL

但如果鏈表中某個節點的 next 指針不是 NULL,而是指向之前的某個節點:

Node → Node → Node  ↑         ↓  ←←←←←←←←←←

這就變成了一個“環形結構”。

?我們怎么知道某個鏈表有沒有環?

你無法一次看完所有節點。你只能從頭開始,一個一個往后走:

while (p != NULL) {p = p->next;
}

正常情況下你最終會走到 p == NULL

但是如果鏈表有環,你會一直繞圈,永遠也走不到 NULL,程序變成死循環。


? 第一種直接想法(失敗):我們是不是能“記住走過的節點”?

想法:

每訪問一個節點,就記住它;
如果某個節點我們第二次看到,就說明有環。

這個思路需要什么?
需要能“記住所有走過的節點”,并判斷是否“已經訪問過”

?? 但我們沒有 STL、沒有哈希表、沒有額外空間!

所以這個方法不符合第一性原則的最低資源要求,我們暫時排除。


那我們換一個思路:我們能否只用兩個指針來檢測環?

想象一下:

如果你在一個環形跑道上,有兩個人:

  • 一個人慢跑(每次走一步)

  • 一個人快跑(每次走兩步)

如果跑道沒有環,快跑的人會直接跑出終點。

如果跑道是環形的,快跑的人遲早會“追上”慢跑的人!

這就是 Floyd’s Cycle Detection Algorithm(龜兔賽跑法)

我們現在從零構建它!


第一步:定義兩個指針

slow = head;
fast = head;
  • slow 每次走一步:slow = slow->next

  • fast 每次走兩步:fast = fast->next->next

?這一步是算法核心,“快指針”在追“慢指針”?

第二步:建立循環

變量含義
slow模擬“正常訪問”的一步步訪問
fast模擬“追趕檢測”的兩步步訪問
slow==fast表示 fast 追上 slow,說明有環
fast==NULL表示鏈表已經結束,無環

問題:我們什么時候會出錯?

  • 如果 fast == NULL:說明走到尾部

  • 如果 fast->next == NULL:再走一步就越界

我們必須確保兩個指針不越界(避免訪問 NULL 的 next):

while (fast != NULL && fast->next != NULL) {slow = slow->next;fast = fast->next->next;if (slow == fast) {// 二者相遇,說明有環}
}

?為什么 slow 和 fast 相遇就說明有環?

因為只有在環中,快指針才有可能“繞回來追上慢指針”

就像操場上,跑得快的人終將追上慢跑的那個人。

如果沒有環,fast 最終會變成 NULL 或 fast->next == NULL,循環終止。

如果鏈表中有環,兩個指針最終會在環中某處相遇:

if (slow == fast)return 1;  // 有環

空鏈表或一個節點鏈表怎么辦?

  • 如果 head == NULL:直接退出循環,返回 0 ?

  • 如果只有一個節點:fast->next == NULL,也會直接退出 ?

?完整代碼

int hasLoop(struct Node* head) {struct Node* slow = head;struct Node* fast = head;// Step 1: 同時從頭開始,每次走一步和兩步while (fast != NULL && fast->next != NULL) {slow = slow->next;             // 慢指針走一步fast = fast->next->next;       // 快指針走兩步if (slow == fast)              // 相遇 → 有環return 1;}// Step 2: 如果快指針走到了鏈表尾部,說明無環return 0;
}

時間 & 空間復雜度分析

復雜度說明
時間復雜度O(n),最壞情況 fast 會走到鏈表盡頭(或追上 slow)
空間復雜度O(1),只用了兩個指針變量,無需額外空間

我們從“什么都不會”出發,只知道我們:

  • 只能走 ->next

  • 不允許記錄歷史

  • 想辦法“檢測重復訪問”

最終我們想到“相遇 → 有環”的思路,從而構建出用兩個指針的檢測算法。

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

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

相關文章

深入理解Java的SPI機制,使用auto-service庫優化SPI

文章目錄一、簡介二、使用1、服務提供者(或者第三方公共):定義接口2、服務提供者:定義實現類3、服務提供者:注冊服務4、構建服務提供者jar包5、客戶端:使用 ServiceLoader 來加載服務三、源碼分析1、源碼2、…

PPT自動化 python-pptx - 10 : 表格(tables)

在日常工作中,我們經常需要制作包含表格的 PowerPoint 演示文稿,以此清晰展示數據或文本信息。手動制作不僅耗時,當數據更新時還需重復操作,效率低下。而 python-pptx 庫為我們提供了自動化操作 PowerPoint 表格的可能。本文將詳細…

在安卓中使用 FFmpegKit 剪切視頻并添加文字水印

在安卓中用到的三方庫:https://github.com/arthenica/ffmpeg-kit 這個庫很強大,支持很多平臺,每個平臺都有各自的分支代碼,用了一段時間,穩定性挺好的, 找到安卓下的分支:FFmpegKit for Andro…

Flask + HTML 項目開發思路

Flask HTML 項目開發思路:以公共資源交易信息展示為例 一、開篇明義——為什么選 Flask 框架 在眾多 Python Web 框架(如 Django、Tornado 等)里,本次項目堅定選擇 Flask,背后有清晰的技術考量: 1. 輕量…

Vue中:deep()和 ::v-deep選擇器的區別

在 Vue.js 中,:deep()和 ::v-deep都是用于穿透組件作用域的深度選擇器,但它們在語法、適用場景和版本支持上存在區別。以下是兩者的核心差異:一、??語法與用法? :Vue2中用 ::v-deep,Vue2中不支持:deep()&#xff0c…

Deep learning based descriptor

1、DH3D: Deep Hierarchical 3D Descriptors for Robust Large-Scale 6DoF Relocalization 論文鏈接 代碼鏈接 這是一篇訓練點云的文章,在訓練出local descriptor之后,通過聚類的方法得出global descriptor,并且提出了hierarchical network&…

PandasAI連接LLM對MySQL數據庫進行數據分析

1. 引言 在之前的文章《PandasAI連接LLM進行智能數據分析》中實現了使用PandasAI連接與DeepSeek模型通過自然語言進行數據分析。不過那個例子中使用的是PandasAI 2.X,并且使用的是本地.csv文件來作為數據。在實際應用的系統中,使用.csv作為庫表的情況比…

FloodFill算法——DFS

FloodFill算法就是用來尋找性質相同的連通快的算法,這篇博客都是用dfs來實現FloodFill算法 1.圖像渲染 題目鏈接:733. 圖像渲染 - 力扣(LeetCode) 題目解析:將和(sr,sc)相連的所有像素相同的…

【BUUCTF系列】[極客大挑戰 2019]LoveSQL 1

本文僅用于技術研究,禁止用于非法用途。 Author:枷鎖 文章目錄一、題目核心漏洞分析二、關鍵解題步驟與技術解析1. 確定列數(ORDER BY)2. 聯合查詢獲取表名3. 爆破字段名4. 提取Flag三、漏洞根源與防御方案1. 漏洞成因2. 防御措施四、CTF技巧…

AI時代,童裝銷售的“指路明燈”

別看現在AI、大數據這些詞眼花繚亂的,當年我剛入行那會兒,也跟你一樣,對著一堆庫存和銷量數據發愁,不知道勁兒該往哪使。童裝銷售這行,看著簡單,其實水挺深。不過呢,這二十多年摸爬滾打下來&…

Swin-Transformer從淺入深詳解

第一部分:出現背景在 Swin Transformer 出現之前,計算機視覺(Computer Vision, CV)領域主要由 CNN (卷積神經網絡) 主導。后來,NLP(自然語言處理)領域的 Transformer 模型被引入 CV,…

如何手動打包 Linux(麒麟系統)的 Qt 程序

gcc版本 gcc版本確保目標系統(運行環境)的 GCC 版本 高于或等于開發環境的版本,否則程序無法在目標平臺運行。通過 gcc -v 可查看當前版本。cmake生成可執行文件 強烈建議在cmakelists添加設置運行時 rpath 為 $ORIGIN/…/lib(相對…

解決 “crypto.hash is not a function”:Vite 從 6.x 升級至 7.x 后 `pnpm run dev` 報錯問題

🚀 作者主頁: 有來技術 🔥 開源項目: youlai-mall ︱vue3-element-admin︱youlai-boot︱vue-uniapp-template 🌺 倉庫主頁: GitCode︱ Gitee ︱ Github 💖 歡迎點贊 👍 收藏 ?評論 …

我的創作紀念日____在 CSDN一年來的成長歷程和收獲

365 天創作札記:在代碼與文字的褶皺里,遇見 1300 束光一年來。點開csdn網站后臺粉絲數的那一刻,1327 這個數字在屏幕上微微發燙。原來那些在深夜敲下的字符、調試到凌晨的代碼示例、反復修改的技術拆解,真的在時光里悄悄織成了一張…

VirtualBox 的 HOST 鍵(主機鍵)是 右Ctrl 鍵(即鍵盤右側的 Ctrl 鍵)筆記250802

VirtualBox 的 HOST 鍵(主機鍵)是 右Ctrl 鍵(即鍵盤右側的 Ctrl 鍵)筆記250802 VirtualBox 的 HOST 鍵(主機鍵)是什么?HOST鍵 是 右Ctrl 鍵VirtualBox 的 主機鍵(Host Key) 是一個…

Zama的使命

全同態加密(Fully Homomorphic Encryption,FHE)實現互聯網端到端加密的使命的重要里程碑。(FHE) 是一種無需解密即可處理數據的技術。它可用于在公共、無需許可的區塊鏈上創建私人智能合約,只有特定用戶才能看到交易數據和合約狀態…

Go語言流式輸出技術實現-服務器推送事件(Server-Sent Events, SSE)

目錄引言背景與技術概述實現技術細節1. HTTP 頭部配置2. 事件格式與發送3. 保持連接與刷新4. 處理連接關閉4.1 使用上下文管理連接生命周期4.2 使用通道管理客戶端連接5. 客戶端交互6.demo7.Go轉發大模型流式輸出demo引言 服務器推送事件(Server-Sent Events, SSE&…

高端房產管理小程序

系統介紹1、用戶端地圖找房:對接地圖API,地圖形式顯示周邊房源,支持新盤和租房兩種模式查詢房價走勢:城市房價走勢,由后臺每月錄入房源搜索:搜索房源,支持多維度篩選房源類型:新盤銷售、房屋租賃…

文本轉語音(TTS)腳本

文本轉語音(TTS)腳本 概述 generate_voice.py 是一個用于生成語音的Python腳本。該腳本提供了文本轉語音(TTS)功能,可以將文本內容轉換為語音文件。 功能特性 文本轉語音: 將輸入的文本轉換為語音文件多種語音選項: 支持不同的語音類型和參數批量處理: 可以處理多個…

磁盤管理與分區

磁盤管理 一、磁盤類型 SATA,SCSI,SAS類型的磁盤,在Linux中用sd來表示。 其中第一塊硬盤為sda,第二塊二sdb,以此類推。 第一塊硬盤的第一個分區為sda1。 nvme類型的磁盤,在Linux中使用nvmeXnYpZ進行表示。 X:數字&…