【Java數據結構】詳解LinkedList與鏈表(二)

目錄

1.????前言~🥳🎉🎉🎉

2.反轉一個單鏈表?

3. 找到鏈表的中間節點

4.輸入一個鏈表,輸出該鏈表中倒數第k個結點。?

??5.合并兩個有序鏈表

6.鏈表分割?

7. 判定鏈表的回文結構

8.輸入兩個鏈表,找出它們的第一個公共結點。?

9.?判斷鏈表中是否有環

10.返回鏈表開始入環的第一個節點

?11.總結???????


1.????前言~🥳🎉🎉🎉

Hello, Hello~ 親愛的朋友們👋👋,這里是E綿綿呀????。

如果你喜歡這篇文章,請別吝嗇你的點贊????和收藏📖📖。如果你對我的內容感興趣,記得關注我👀👀以便不錯過每一篇精彩。

當然,如果在閱讀中發現任何問題或疑問,我非常歡迎你在評論區留言指正🗨?🗨?。讓我們共同努力,一起進步!

加油,一起CHIN UP!💪💪

🔗個人主頁:E綿綿的博客
📚所屬專欄:

1.?JAVA知識點專欄

? ? ?? ?深入探索JAVA的核心概念與技術細節

2.JAVA題目練習

? ? ? ??實戰演練,鞏固JAVA編程技能

3.c語言知識點專欄

? ? ? ? 揭示c語言的底層邏輯與高級特性

4.c語言題目練習

? ? ? ? 挑戰自我,提升c語言編程能力

📘 持續更新中,敬請期待?????

這篇文章我們將給大家帶來一些單鏈表的面試題,都很有意思,來看一下吧。

2.反轉一個單鏈表?

? 給你單鏈表的頭節點?head?,請你反轉鏈表,并返回反轉后的鏈表。


我們的解決方法是依次頭插法:

最開始時我們需要將第一個節點的next值變為null,使其變成最后的節點,就產生了新的鏈表。而后依次將原始鏈表中的第二個節點,第三個節點直至最后一個節點頭插到新鏈表中。

這樣就翻轉成功了

完整代碼如下:?

public void reverseList() {if(head==null)return;ListNode cur=head.next;ListNode prev;head.next=null;while(cur!=null){prev=cur.next;cur.next=head;head=cur;cur=prev;}}

這是該題的鏈接 :?翻轉鏈表? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??

3. 找到鏈表的中間節點

? ?給你單鏈表的頭結點?head?,請你找出并返回鏈表的中間結點。

? ?如果有兩個中間結點,則返回第二個中間結點。


該題的思路實現是設置兩個引用:slow 慢引用 和 fast 快引用?

fast 和 slow 同時從head開始遍歷,但是fast一次走兩步,slow一次只走一步,最后我們會發現當 fast遍歷完成后 ,對應的slow正好是鏈表的中間節點或者第二個中間節點。

fast遍歷完成的標志是fast.next=null或者fast=null

? 完整代碼如下:

public ListNode middleNode(ListNode head) {ListNode fast=head;ListNode  slow=head;while(fast!=null&&fast.next!=null){fast=fast.next.next;slow=slow.next;}return slow;
}

該題鏈接:求鏈表中間結點?

4.輸入一個鏈表,輸出該鏈表中倒數第k個結點。?



該題有兩種思路

?第一種思路:?


第二種思路:


所以我們采用第二種思路去做題,且我們還需要注意k的合法性。

整體代碼如下:

public ListNode FindKthToTail(ListNode head,int k){
if(head==null){
return null;
}
ListNode fast = head;
ListNode slow = head;
//1.判斷k值的合法性
if( k<=0 ){
System.out.println("k值不合法");
return null;
}
//2.讓fast 提前走 k-1 步
while(k-1>0){
if(fast == null |l fast.next ==null){
System.out.println("k值不合法”);
return null;
}
fast = fast.next;
k--;
}
while(fast !=null && fast.next != null){
fast = fast.next;slow = slow.next;
return slow;
}
}

該題題目已下架,無鏈接。



??5.合并兩個有序鏈表


將兩個升序鏈表合并為一個新的?升序?鏈表并返回。新鏈表是通過拼接給定的兩個鏈表的所有節點組成的。?

?解題思路:

1.先創建一個新的鏈表

2.讓cur1 和 cur2遍歷兩個鏈表,遇到的節點逐個比較,將值小的節點往新鏈表的末尾tail進行尾插

3.上述循環結束后,要判斷有無鏈表還有剩余元素,把剩余的元素尾插到新鏈表的末尾。

? 完整代碼如下:

public  static ListNode mergeTwoLists(ListNode list1, ListNode list2){//將兩個有序鏈表合并為一個有序鏈表ListNode head1=list1;ListNode head2=list2;ListNode head=new ListNode(-1);ListNode cur=head;while(head1!=null&&head2!=null){if(head1.value>head2.value){cur.next=head2;cur=cur.next;head2=head2.next;}else{cur.next=head1;cur=cur.next;head1=head1.next;}}while(head1!=null){cur.next=head1;cur=cur.next;head1=head1.next;}while(head2!=null){cur.next=head2;cur=cur.next;head2=head2.next;}return head.next;}

? 該題鏈接:合并兩個有序鏈表

6.鏈表分割?

現有一鏈表的頭引用?pHead,給一定值x,編寫一段代碼將所有小于x的結點排在其余結點之前,且不能改變原來的數據順序,返回重新排列后的鏈表的頭指針。

? ?解題思路:

1.創建兩個鏈表,一個鏈表尾插值小于x的節點,另一個鏈表中插值大于等于x的節點

2.遍歷原鏈表,將鏈表中的節點往兩個新鏈表中尾插

3.將兩個鏈表拼接

但是這種思路仍然存在較大的問題,什么問題呢?


1.我們傳入的x值比節點中val都大或者都小,那么存在一個問題就是有一個鏈表中的內容為空,那么按照上面的思路走時,必然會出現空指針異常的情況。

解決方法:??當第一個區間為空時,那么直接返回ca


2.最后一個節點分到小于x的區間,那么最后一個節點的next并不是null,所以此時我們必須手動將 cb.next=null; 預防最后一個節點的next不是null,從而報錯。?

完整代碼如下:

  public static ListNode partition(ListNode pHead, int x) {//給一定值x,該方法將所有小于x的結點排在其余結點之前,且不能改變原來的數據順序,返回重新排列后的鏈表的頭指針。if(pHead==null)return  null;ListNode cur=pHead;ListNode  sa=null;ListNode  sb=null;   //小于x的結點所在鏈表ListNode  ca=null;ListNode  cb=null; //大于x的結點所在鏈表while(cur!=null){if(cur.value<x){if(sa==null){sa=cur;sb=cur;cur=cur.next;}else{sb.next=cur;sb=cur;cur=cur.next;}}else{if(ca==null){ca=cur;cb=cur;cur=cur.next;}else{cb.next=cur;cb=cur;cur=cur.next;} }}//拼接兩個鏈表if(sa==null)return  ca;//如果不存在小于X的結點,則直接返回大于x的鏈表,否則按如下執行會報錯if(ca!=null)cb.next=null;//將鏈表中的最后一個結點的next值變為null,防止其循環從而報錯sb.next=ca;return sa;}

題目鏈接:鏈表分割_牛客題霸_牛客網

7. 判定鏈表的回文結構



解題思路實現:

1.找到鏈表的中間節點,找中間節點:采用快慢指針就行了
2.對鏈表的后半部分進行反轉

3.將兩個鏈表從前往后逐個節點進行比對,如果比對之后發現所有節點的值域都相同,則是回文鏈表,否則不是.

并且在循環時還需注意當鏈表為奇數或偶數時,判定循環結束的標志不同:

?奇數是head==slow時結束

?偶數是head.next=slow時結束

所以完整代碼如下:


public static  boolean checkPalindrome(ListNode A) {//判斷鏈表是否為回文結構if(A==null||A.next==null)return true;ListNode slow=A;ListNode fast=A;while(fast!=null&&fast.next!=null){fast=fast.next.next;slow=slow.next;}ListNode cur=slow.next;while(cur!=null){ListNode  curnext=cur.next;cur.next=slow;slow=cur;cur=curnext;}ListNode head=A;while(head!=slow){if(head.value!=slow.value)return false;if(head.next==slow)return true;head=head.next;slow=slow.next;}return true;}

注意:在執行完該方法后鏈表結構會被破壞掉,之后如果還對該鏈表進行操作,結果會和我們預想的結果不一樣。

該題鏈接:鏈表的回文結構_牛客題霸_牛客網?

8.輸入兩個鏈表,找出它們的第一個公共結點。?

給你兩個單鏈表的頭節點?headA?和?headB?,請你找出并返回兩個單鏈表相交的起始節點。如果兩個鏈表不存在相交節點,返回?null?。?


下面是兩個節點相交的各類情況:


從上述鏈表相交的情況看出,兩個單鏈表只要相交,從交點開始,到其后續所有的節點都是兩個鏈表中公共的節點
檢測兩個鏈表是否相交:分別找到兩個鏈表中的最后一個節點,然后檢測這兩個節點的地址是否相同即可:如果地址相同則相交,否則不相交

解題思路:

1.讓較長的鏈表先走兩個鏈表的差值步數

2.再讓兩個鏈表同時往后走,直到遇到地址相同的交點,沒有則返回null

  public static  ListNode getIntersectionNode(ListNode headA, ListNode headB) {//給你兩個單鏈表的頭節點 headA 和 headB ,找出并返回兩個單鏈表相交的起始節點。if(headA==null||headB==null)return null;ListNode cur1=headA;ListNode cur2=headB;int length1=0;int length2=0;while(cur1!=null){length1++;cur1=cur1.next;}while(cur2!=null){length2++;cur2=cur2.next;}cur1=headA;cur2=headB;if(length1>length2){for(int i=0;i<length1-length2;i++){cur1=cur1.next;}}else{for(int i=0;i<length2-length1;i++){cur2=cur2.next;}}while(cur1!=null){if(cur1==cur2)return cur1;cur1=cur1.next;cur2=cur2.next;}return null;}

題目鏈接:找出兩個鏈表的第一個公共節點

9.?判斷鏈表中是否有環

給你一個鏈表的頭節點?head?,判斷鏈表中是否有環。?


解題思路:

設計快慢指針去解決,即慢指針一次走一步,快指針一次走兩步,兩個指針從鏈表起始位置開始運行,如果鏈表帶環則一定會在環中相遇,否則快指針率先走到鏈表的末尾。

擴展問題:

1.為什么快指針每次走兩步,慢指針走一步可以?

假設鏈表帶環,兩個指針最后都會進入環,快指針先進環,慢指針后進環。當慢指針剛進環時,可能就和快指針相遇了,最差情況下兩個指針之間的距離剛好就是環的長度。此時,兩個指針每移動一次,之間的距離就縮小一步,不會出現始終相遇不到的情況,因此:在慢指針走到一圈之前,快指針肯定是可以追上慢指針的,即相遇。

2.快指針一次走3步,走4步,...n步行嗎?

假設:快指針每次走3步,滿指針每次走一步,此時快指針肯定先進環,慢指針后來才進環。假設慢指針進環時候,快指針的位置如圖所示:

此時按照上述方法來繞環移動,每次快指針走3步,慢指針走1步,它們是永遠不會相遇的,因此不行。
只有快指針走2步,慢指針走一步才可以,因為每移動一次,它們之間的距離就縮小一步,無論如何都能相遇。

所以我們在環問題中設置快慢指針,都是將快指針設置為一次兩步,慢指針一次一步,這樣當存在圈時無論如何都會相遇。

? ? 完整代碼如下:

 public static  boolean hasCycle(ListNode head) {//給你一個鏈表的頭節點 head ,判斷鏈表中是否有環。if(head==null||head.next==null)//只有一個節點時默認絕對不存在環return false;ListNode slow=head;ListNode  fast=head;while(fast!=null&&fast.next!=null){fast=fast.next.next;slow=slow.next;if(slow==fast)return true;}return false;}

題目鏈接 :判斷鏈表中是否有環

10.返回鏈表開始入環的第一個節點

給定一個鏈表的頭節點 ?head?,返回鏈表開始入環的第一個節點。?如果鏈表無環,則返回?null?

解題思路:

設計一個慢指針,一個快指針,快指針一次兩步,慢指針一次一步。使兩指針相遇而后讓一個指針從鏈表起始位置開始遍歷鏈表,同時也讓一個指針從相遇點的位置開始繞環運行,兩個指針都是每次均走一步,最終肯定會在入口點的位置相遇。??

它們肯定會在入口點相遇的證明如下:


上圖中的H為鏈表的起始點,E為環入口點,M為慢速指針相遇點,設環的長度為R,H到E的距離為L ,E到M的距離為X,則M到E的距離為R-X
在快慢指針相遇過程時,快慢指針相遇時所走的路徑長度:
fast:L +X + nR? ? ? slow:L+ X
注意:

1.當慢指針進入環時,快指針可能已經在環中繞了n圈了,n至少為1。

因為:快指針先進環走到M的位置,最后又在M的位置與慢指針相遇
2.慢指針進環之后,快指針肯定會在慢指針走一圈之內追上慢指針

因為:慢指針進環后,快慢指針之間的距離最多就是環的長度,而兩個指針在移動時,每次它們至今的距離都縮減一步,因此在慢指針移動一圈之前快指針肯定是可以追上慢指針的
而快指針速度是滿指針的兩倍。

所以有如下關系是:

2 *(L+X)=L+X+nR

L+X=nR

L=nR-X(n為1,2,3,4..……,n的大小取決于環的大小,環越小n越大)
極端情況下,假設n=1,此時:L=R-X


所以由此得知一個指針從鏈表起始位置運行,一個指針從相遇點位置繞環,每次都走一步,兩個指針無論如何最終都會在入口點的位置相遇。

? ?完整代碼如下:

public static  ListNode detectCycle(ListNode head) {//給定一個鏈表的頭節點 head ,返回鏈表開始入環的第一個節點。 如果鏈表無環,則返回 null。if(head==null||head.next==null)return null;ListNode slow=head;ListNode  fast=head;while(fast!=null&&fast.next!=null){fast=fast.next.next;slow=slow.next;if(slow==fast){slow=head;while(slow!=fast){slow=slow.next;fast=fast.next;}return slow;}}return null;}

?11.總結

所以對于這10個面試題我們就講述清楚了,并且我還把其中的部分題目當作特殊方法加入到模擬的無頭單向非循環鏈表類中。

對于該無頭單向非循環鏈表的模擬實現和其具體使用放到碼云里了,大家可以看下:無頭單向非循環鏈表的模擬實現和其具體使用(此外還往模擬的鏈表內部添加了一些特殊方法)

下篇文章將給大家帶來LinkedList的模擬實現和具體使用。

在此,我們誠摯地邀請各位大佬們為我們點贊、關注,并在評論區留下您寶貴的意見與建議。讓我們共同學習,共同進步,為知識的海洋增添更多寶貴的財富!🎉🎉🎉????💕💕🥳👏👏👏?

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

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

相關文章

棧與隊列練習題(2024/5/31)

1有效的括號 給定一個只包括 (&#xff0c;)&#xff0c;{&#xff0c;}&#xff0c;[&#xff0c;] 的字符串 s &#xff0c;判斷字符串是否有效。 有效字符串需滿足&#xff1a; 左括號必須用相同類型的右括號閉合。左括號必須以正確的順序閉合。每個右括號都有一個對應的…

云服務和云備份的區別是什么?

隨著云計算的興起&#xff0c;云備份與云服務被越來越多的企業和個人所關注&#xff0c;在云計算中云服務與云備份之間還是有一定的區別的&#xff0c;本文就來介紹一下云服務和云備份之間的區別。 云服務和云備份主要的區別在備份對象、推薦場景和數據一致性等方面。 備份對象…

打印機的ip不同且連不上

打印機的ip不同且連不上 1.問題分析2.修改網段3.驗證網絡 1.問題分析 主要是打印機的網段和電腦不在同一個網段 2.修改網段 3.驗證網絡

Web前端三大主流框:React、Vue 和 Angular

在當今快速發展的 Web 開發領域&#xff0c;選擇合適的前端框架對于項目的成功至關重要。React、Vue 和 Angular 作為三大主流前端框架&#xff0c;憑借其強大的功能和靈活的特性&#xff0c;贏得了眾多開發者的青睞。本文將對這三大框架進行解析&#xff0c;幫助開發者了解它們…

dubbo復習:(12)服務器端的異步和客戶端的異步調用

一、服務器端接口的定義和實現&#xff1a; package cn.edu.tju.service;import java.util.concurrent.CompletableFuture;public interface AsyncService {/*** 同步調用方法*/String invoke(String param);/*** 異步調用方法*/CompletableFuture<String> asyncInvoke(…

C/C++學習筆記 C讀取文本文件

1、簡述 要讀取文本文件&#xff0c;需要按照以下步驟操作&#xff1a; 首先&#xff0c;使用該函數打開文本文件fopen()。其次&#xff0c;使用fgets()或fgetc()函數從文件中讀取文本。第三&#xff0c;使用函數關閉文件fclose()。 2、每次從文件中讀取一個字符 要從文本文…

整理一下win7系統java、python等各個可安裝版本

最近使用win7系統&#xff0c;遇到了很多版本不兼容的問題&#xff0c;把我現在安裝好的可使用的分享給大家 jdk 1.8 maven-3.9.6 centos 7 python 3.7.4 docker DockerToolbox-18.01.0-ce win10是直接一個docker軟件&#xff0c;win7要安裝這三個 datagrip-2020.2.3 d…

2.1Docker安裝MySQL8.0

2.1 Docker安裝MySQL8.0 1.拉取MySQL docker pull mysql:latest如&#xff1a;拉取MySQL8.0.33版本 docker pull mysql:8.0.332. 啟動鏡像 docker run -p 3307:3306 --name mysql8 -e MYSQL_ROOT_PASSWORDHgh75667% -d mysql:8.0.33-p 3307:3306 把mysql默認的3306端口映射…

CentOs-7.5 root密碼忘記了,如何重置密碼?

VWmare軟件版本&#xff1a;VMware Workstation 16 Pro Centos系統版本&#xff1a;CentOS-7.5-x86 64-Minimal-1804 文章目錄 問題描述如何解決&#xff1f; 問題描述 長時間沒有使用Linux系統&#xff0c;root用戶密碼忘記了&#xff0c;登陸不上系統&#xff0c;如下圖所示…

【網絡安全】Web安全基礎 - 第一節:使用軟件及環境介紹

VMware VMware&#xff0c;是全球云基礎架構和移動商務解決方案的佼佼者。 VMware可是一個總部位于美國加州帕洛阿爾托的計算機虛擬化軟件研發與銷售企業呢。簡單來說&#xff0c;它就是通過提供虛擬化解決方案&#xff0c;讓企業在數據中心改造和公有云整合業務上更加得心應…

QImage和QPixmap的區別和使用

一、基本概念和特點 QImage 概念&#xff1a;QImage是Qt庫中用于處理圖像數據的一個類。它提供了直接訪問和操作圖像像素的接口。特點&#xff1a; 可以獨立于屏幕分辨率和設備處理圖像。支持讀取和保存多種圖像格式&#xff0c;如PNG、JPEG、BMP等。可以在沒有圖形界面的情況…

圖論第二天

最近加班時間又多了&#xff0c;隨緣吧&#xff0c;干不動就辭唄。真是想歇幾天了&#xff0c;題不能停&#xff01;&#xff01;今天目前只做了一道題&#xff0c;先用兩種方式把他搞出來。 695. 島嶼的最大面積 class Solution { public:int neighbor[4][2] {1,0,0,-1,-1,…

Linux系統管理基礎002

Linux系統管理基礎之文件管理二 Linux文件管理是系統管理中的重要組成部分 1.文件與目錄的基本概念 2. 特殊目錄與文件 3. 文件與目錄的操作 4. 文件權限管理 5. 查找處理文件 6. 關聯技巧 今天給大家介紹一下目錄的結構 1.文件與目錄的基本概念 管理類目錄&#xff1a; …

FreeRTOS基礎(三):動態創建任務

上一篇博客&#xff0c;我們講解了FreeRTOS中&#xff0c;我們講解了創建任務和刪除任務的API函數&#xff0c;那么這一講&#xff0c;我們從實戰出發&#xff0c;規范我們在FreeRTOS下的編碼風格&#xff0c;掌握動態創建任務的編碼風格&#xff0c;達到實戰應用&#xff01; …

用貪心算法進行10進制整數轉化為2進制數

十進制整數轉二進制數用什么方法&#xff1f;網上一搜&#xff0c;大部分答案都是用短除法&#xff0c;也就是除2反向取余法。這種方法是最基本最常用的&#xff0c;但是計算步驟多&#xff0c;還容易出錯&#xff0c;那么還有沒有其他更好的方法嗎&#xff1f; 一、短除反向取…

AdroitFisherman模塊安裝日志(2024/5/31)

安裝指令 pip install AdroitFisherman-0.0.29.tar.gz -v 安裝條件 1:Microsoft Visual Studio Build Tools 2:python 3.10.x 顯示輸出 Using pip 24.0 from C:\Users\12952\AppData\Local\Programs\Python\Python310\lib\site-packages\pip (python 3.10) Processing c:\u…

matlab GUI界面設計

【實驗內容】 用MATLAB的GUI程序設計一個具備圖像邊緣檢測功能的用戶界面&#xff0c;該設計程序有以下基本功能&#xff1a; &#xff08;1&#xff09;圖像的讀取和保存。 &#xff08;2&#xff09;設計圖形用戶界面&#xff0c;讓用戶對圖像進行彩色圖像到灰度圖像的轉換…

3-哈希表-21-兩個數組的交集-LeetCode349

3-哈希表-21-兩個數組的交集-LeetCode349 參考&#xff1a;代碼隨想錄 LeetCode: 題目序號349 更多內容歡迎關注我&#xff08;持續更新中&#xff0c;歡迎Star?&#xff09; Github&#xff1a;CodeZeng1998/Java-Developer-Work-Note 技術公眾號&#xff1a;CodeZeng1998&…

2.1 OpenCV隨手簡記(二)

為后續項目學習做準備&#xff0c;我們需要了解LinuxOpenCV、Mediapipe、ROS、QT等知識。 一、圖像顯示與保存 1、基本原理 1.1 圖像像素存儲形式 首先得了解下圖像在計算機中存儲形式&#xff1a;(為了方便畫圖&#xff0c;每列像素值都寫一樣了)。對于只有黑白顏色的灰度…

[有監督學習]2.詳細圖解正則化

正則化 正則化是防止過擬合的一種方法&#xff0c;與線性回歸等算法配合使用。通過向損失函數增加懲罰項的方式對模型施加制約&#xff0c;有望提高模型的泛化能力。 概述 正則化是防止過擬合的方法&#xff0c;用于機器學習模型的訓練階段。過擬合是模型在驗證數據上產生的誤…