三個有意思的鏈表面試題的完成

上一篇博客我們已經完成了鏈表的所有內容,那么這一篇博客我們來看一下三個特別有意思的鏈表題目。

**第一個題目如下:**

在這里插入圖片描述
在這里插入圖片描述
相信不少朋友看到這題目就已經暈了,那就簡單說明下這個題目,題目就是創建一個鏈表,其中每個節點有兩部分–指針域與數值域,指針域里也有兩個指針next(指向下一個節點),random(隨機指向),要求我們拷貝一份這個鏈表,使原鏈表和復制鏈表中的這些指針能夠表示相同的鏈表狀態。復制鏈表中的指針都不應指向原鏈表中的節點 。
在這里插入圖片描述

也就是上圖的形式,這個題目如果單純的只拷貝一份鏈表和每個節點的val,相信大家可以很快的做出,也就是遍歷一下原鏈表,遍歷一個節點創建一個新的節點并拷貝值,最后將節點連接形成鏈表即可。但現在增加了一個random指針,我們該如何解決這個問題呢?

受限于當前的知識,我們可用的方法很少,下面是一個很巧妙的思路:
1、創建新的節點,構造新鏈表
在這里插入圖片描述
我們可以遍歷一個節點拷貝一個節點,并且將這個新的節點插入至原節點的后面。

2、完成random的指向
在這里插入圖片描述
當我們把這一步以圖像的形式展現,我們就可以發現新鏈表當前節點的random指針是不是指向原鏈表原節點的random->next指向的節點

3、取下拷貝的節點,形成題目要求的鏈表
在這里插入圖片描述
把這個節點連接形成新的鏈表,我們可以使用之前學過的尾插,頭插都是可以的。

最后還有一個小細節,就是如果我們只取下節點,那原鏈表是不是被我們斷開了,我們可以恢復原鏈表的結構也可以不恢復,題目里沒有說明就不用管。

代碼如下:

/*** Definition for a Node.* struct Node {*     int val;*     struct Node *next;*     struct Node *random;* };*/
struct Node* copyRandomList(struct Node* head) {struct Node*pcur=head;//創建遍歷原鏈表的指針pcurwhile(pcur){struct Node*newnode=(struct Node*)malloc(sizeof(struct Node));newnode->val=pcur->val;newnode->next=pcur->next;pcur->next=newnode;pcur=newnode->next;}//這一部分就是拷貝節點,并插入原節點后面struct Node*cur=head;//同樣為遍歷鏈表的節點while(cur){struct Node*newnode=cur->next;if(cur->random==NULL){newnode->random=NULL;}else{newnode->random=cur->random->next;}cur=newnode->next;}//這一部分完成的是新節點的random的指向struct Node*phead=NULL;//創建一個新的鏈表phead為頭指針,ptail為尾指針struct Node*ptail=NULL;struct Node*Cur=head;while(Cur){struct Node*node=Cur->next;//node指向的是原鏈表的新節點struct Node*next=node->next;//next指向的是原鏈表的原節點if(ptail==NULL)//如果新鏈表為空{phead=ptail=node;}else//鏈表不為空{ptail->next=node;ptail=ptail->next;}Cur=next;}return phead;//返回新鏈表的頭}
**第二個題目如下:**

在這里插入圖片描述
在這里插入圖片描述
這道題目代碼比較簡單,想要理解透徹還是有一定難度的。

思路如下:
在這里插入圖片描述
就是使用快慢指針,快指針一步走兩個節點,慢指針一步走一個節點,讓慢指針去追這個快指針,當追上的時候也就是fast==slow,那就證明帶環,如果一直追不上那就不帶環。

那一定追的上嗎?有沒有可能出現錯過的情況?快指針可以一步走三個節點嗎?走三個節點會不會錯過呢?這幾個問題就是我們現在需要解決的。

第一個問題:那一定追的上嗎?有沒有可能出現錯過的情況?

在這里插入圖片描述
從現在開始,fast走兩步,slow走一步,那么兩指針每走一步,它們之間的距離減小1,所以N取任何值slow與fast指針都會相遇,故不存在錯過的情況。

第二個問題:快指針可以一步走三個節點嗎?走三個節點會不會錯過呢?

由上面的圖我們可以推出:
在這里插入圖片描述
那么我們可以總結一下:
當N為偶數時,無論R為奇數偶數,都能夠追上,也就是不會錯過。
當N為奇數,R為奇數時,能夠追上;
當N為奇數,R為偶數時,永遠追不上。

但是存不存在N為奇數,R為偶數這種情況?
在這里插入圖片描述
由上面得出的結論就是fast一步走三個節點,一定能追上。

根據上面的推導過程,fast一步走4個節點、5個節點都是可以推出來的。

代碼實現很簡單:

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     struct ListNode *next;* };*/
bool hasCycle(struct ListNode *head) {struct ListNode*fast=head;struct ListNode*slow=head;while(fast&&fast->next){fast=fast->next->next;slow=slow->next;if(fast==slow){return true;}}return false;
}
**第三個題目:**

在這里插入圖片描述
這個題目就是在上一個題目的基礎上更加深入一點,需要我們返回這個循環的初始節點;

第一步:判斷環的有無
因為這一步與上一個題目基本一樣,所以我這里就不再重復了;

第二步:讓slow走到fast的位置,也就是讓兩個指針相遇定義為meet,返回當前節點,這一步也可以通過前一個題目實現;

第三步:讓pcur從鏈表的頭開始走,同時meet也開始在環內走,當兩者相等時,兩指針指向的節點就是開始循環的節點。

下面我們就來討論為什么:
在這里插入圖片描述
代碼實現:

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     struct ListNode *next;* };*/struct ListNode*fastnode(struct ListNode*head)
{struct ListNode*fast=head;struct ListNode*slow=head;while(fast&&fast->next){fast=fast->next->next;slow=slow->next;if(slow==fast){return fast;//這里我沒有創建新的meet指針,當兩者相等時,返回其中一個效果相同}}return NULL;//判斷是否有環
}struct ListNode *detectCycle(struct ListNode *head) {struct ListNode*fast=fastnode(head);if(fast==NULL)//如果鏈表沒有環就直接返回NULL{return NULL;}struct ListNode*slow=head;while(slow!=fast)//這一步就是讓兩指針相遇,返回相遇時的節點,也就是環開始的節點{slow=slow->next;fast=fast->next;}return fast;
}

最后一個題還有一種做法,那就是將meet指向的節點斷開,那現在整個題目就變為了相交鏈表求相交節點的問題了,這里只簡單的說明一下思路,有興趣的可以下來實現一下;
在這里插入圖片描述

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

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

相關文章

深入探索Java中的流式編程:優雅地處理集合數據

Java流式編程(Stream API)是Java 8引入的一項重要特性,它為處理集合數據提供了一種更為優雅和函數式的方式。通過流式操作,開發者可以以更簡潔、更直觀的方式處理數據,從而提高代碼的可讀性和可維護性。本文將深入探討…

Android14 - 繪制系統 - 概覽

從Android 12開始,Android的繪制系統有結構性變化, 在繪制的生產消費者模式中,新增BLASTBufferQueue,客戶端進程自行進行queue的生產和消費,隨后通過Transation提交到SurfaceFlinger,如此可以使得各進程將緩…

【vue3+elementuiplus】el-select下拉框會自動觸發校驗規則

場景:編輯彈框省份字段下拉框必填,觸發方式change,有值第一次打開不會觸發校驗提示,關閉彈框再次打開觸發必填校驗提示,但是該字段有值 問題的原因是:在關閉彈層事件中,我做了resetfileds&…

SpringBoot + MybatisPlus

SpringBoot MybatisPlus 整合記錄 1. 硬件軟件基本信息2. 相關鏈接3. 通過idea快速生成一個Springboot項目4. 啟動報錯問題解決問題一:Springboot啟動的時候報錯提示 “沒有符合條件的Bean關于Mapper類型”問題二:啟動的時候提示需要一個Bean&#xff0…

電磁仿真--CST網格介紹

1. 簡介 網格會影響仿真的準確性和速度,花時間理解網格化過程是很重要的。 CST 中可用的數值方法包括FIT、TLM、FEM、MoM,使用不同類型的網格: FIT和TLM:六面體 FEM:四面體、平面 MoM:表面 CFD&#…

深入理解與防御跨站腳本攻擊(XSS):從搭建實驗環境到實戰演練的全面教程

跨站腳本攻擊(XSS)是一種常見的網絡攻擊手段,它允許攻擊者在受害者的瀏覽器中執行惡意腳本。以下是一個XSS攻擊的實操教程,包括搭建實驗環境、編寫測試程序代碼、挖掘和攻擊XSS漏洞的步驟。 搭建實驗環境 1. 安裝DVWA&#xff…

【408真題】2009-16

“接”是針對題目進行必要的分析,比較簡略; “化”是對題目中所涉及到的知識點進行詳細解釋; “發”是對此題型的解題套路總結,并結合歷年真題或者典型例題進行運用。 涉及到的知識全部來源于王道各科教材(2025版&…

推薦一個快速開發接私活神器

文章目錄 前言一、項目介紹二、項目地址三、功能介紹四、頁面顯示登錄頁面菜單管理圖表展示定時任務管理用戶管理代碼生成 五、視頻講解總結 前言 大家好!我是智航云科技,今天為大家分享一個快速開發接私活神器。 一、項目介紹 人人開源是一個提供多種…

SCSS配置教程

SCSS(Sassy CSS)是 Sass(Syntactically Awesome Stylesheets)的一種語法,它是一種 CSS 預處理器,允許你使用變量、嵌套規則、混合(mixin)、函數等高級功能來編寫 CSS,從而…

Golang | Leetcode Golang題解之第112題路徑總和

題目: 題解: func hasPathSum(root *TreeNode, sum int) bool {if root nil {return false}if root.Left nil && root.Right nil {return sum root.Val}return hasPathSum(root.Left, sum - root.Val) || hasPathSum(root.Right, sum - roo…

C++常見知識點總結

常見字符 * 注釋:/* 這是一個注釋*/乘法:a * b取值運算符:*指針變量,int a 4,*a ????指針變量:數據類型 *變量名, int *no &bh&#xff0…

SAP揭秘者-怎么執行生產訂單ATP檢查及其注意點

文章摘要: 上篇文章給大家介紹生產訂單ATP檢查的相關后臺配置,大家可以按照配置步驟去進行配置,配置完之后,我們接下來就是要執行ATP檢查。本篇文章具體給大家介紹怎么來執行生產 訂單ATP檢查及其注意點。 執行生產訂單ATP檢查的…

Qt for android 獲取USB設備列表(二)JNI方式 獲取

簡介 基于上篇 [Qt for android 獲取USB設備列表(一)Java方式 獲取], 這篇就純粹多了, 直接將上篇代碼轉換成JNI方式即可。即所有的設備連接與上篇一致。 (https://listentome.blog.csdn.net/article/details/139205850) 關鍵代碼…

Android卡頓丟幀低內存與adb shell內存狀態

Android卡頓丟幀低內存與adb shell內存狀態 卡頓丟幀除了CPU/GPU層面,另外,也需要特別注意整機低內存情況。kswapd0 是一個內核工作線程,內存不足時會被喚醒,做內存回收工作。 當內存頻繁在低水位的時候,kswapd0 會被頻…

webgl three 項目常用操作

分組 const group1 new THREE.Group(); //所有高層樓的父對象group1.name "高層";for (let i 0; i < 5; i) {const geometry new THREE.BoxGeometry(20, 60, 10);const material new THREE.MeshLambertMaterial({color: 0x00ffff});const mesh new THREE.Me…

Linux基礎(六):Linux 系統上 C 程序的編譯與調試

本篇博客詳細分析&#xff0c;Linux平臺上C程序的編譯過程與調試方法&#xff0c;這也是我們后續程序開發的基礎。 目錄 一、第一個hello world程序 1.1 創建.c文件 1.2 編譯鏈接 運行可執行程序 二、編譯鏈接過程 2.1 預編譯階段 2.2 編譯階段 2.3 匯編階段 2.4 鏈…

一千題,No.0025(Chess For Three)

描述 Three friends gathered to play a few games of chess together. In every game, two of them play against each other. The winner gets 2 points while the loser gets 0, and in case of a draw, both players get 1 point each. Note that the same pair of playe…

【MySQL精通之路】SQL語句(3)-鎖和事務語句

目錄 1.START TRANSACTION、COMMIT和ROLLBACK語句 2.無法回滾的語句 3.導致隱含COMMIT的語句 4.SAVEPOINT、ROLLBACK TO SAVEPOINT和RELEASE SAVEPOINT語句 5.LOCK INSTANCE FOR BACKUP和UNLOCK INSTANCE語句 6.LOCK TABLE和UNLOCK TABLES語句 6.1 表鎖獲取 6.2 表鎖釋放…

qemu+gdb調試linux內核

打開CONFIG_DEBUG_INFO,編譯內核 通過圖形菜單配置該宏,執行make menuconfig。 kernel hacking —> compile-time checks and compiler options —> compile the kernel with debug info 驗證是否打開成功,grep -nr “CONFIG_DEBUG_INFO” .config。 打開成功,然后…

plsql 學習

過程化編程語言 賦值&#xff1a;&#xff1a; ||&#xff1a;連接符號 dbms_output.put_line() :輸出的語句 var_name ACCOUNTLIBRARY.USERNAME%type; 變量名&#xff1b;某個表的數據類型&#xff1b;賦值給變量名 用下面的方法更好用 異常exception 循…