java反轉鏈表的多種解決方法舉例詳解
反轉鏈表的三種方式
1,使用棧解決
棧是最容易的一種方式了,因為棧是先進后出。實現(xiàn)原理就是把鏈表節(jié)點一個個入棧,全部入棧之后再一個個出棧,出棧的時候在把節(jié)點按照出棧的順序組成一個新的鏈表。
原理如圖:
代碼如下:
public ListNode ReverseList(ListNode head){ Stack<ListNode> stack = new Stack<>(); //把全部節(jié)點都壓入棧中 while(head != null){ stack.push(head); head = head.next; } //如果stack棧里面沒有數(shù)據(jù),說明head是一個空指針,因此可以直接返回 //不需要進行后續(xù)計算 if(stack.isEmpty()){ return null; } ListNode node = stack.pop();//出棧的第一個節(jié)點成為第一個新鏈表的第一個節(jié)點 ListNode dummy = node; //保留頭節(jié)點,用于最后的返回 //把棧中的節(jié)點全部出棧,然后重新連成一個新的鏈表 while(!stack.isEmpty()){ node.next = stack.pop(); node = node.next;//更換鏈表的最后一個元素 } //最后一個節(jié)點就是反轉前的頭節(jié)點,需要讓他的next為null //不然可能構成環(huán) node.next = null; return dummy;//最后返回保存好的頭節(jié)點 }
2,雙指針實現(xiàn)
利用兩個指針來保存鏈表中數(shù)據(jù),一個指針用來存儲當前節(jié)點中next元素中更改后的值,另一個指針來指向下一個需要更改節(jié)點的地址。
原理如圖:
代碼如下:
public ListNode ReverseList(ListNode head) { //當前節(jié)點中next元素改變后的值 //初始值為null是因為更改后 原第一個元素 改后最后一個元素 //next指向的值為null ListNode ChangeNode = null; while (head != null) { //先保存當前訪問的節(jié)點的下一個節(jié)點 //留著while循環(huán)最后更新數(shù)據(jù)并且 ListNode nextNode = head.next; //把當前節(jié)點中next元素進行更改,使其可以指向前一個元素 head.next = ChangeNode; //更新ChangeNode指針,用于下一次節(jié)點next元素更新 ChangeNode = head; //更新節(jié)點,去往下一個節(jié)點 head = nextNode; } //循環(huán)之后ChangeNode指向的值為 原最后一個節(jié)點 改后第一個節(jié)點 //所以返回ChangeNode就是改后的頭節(jié)點 return ChangeNode; }
3,遞歸實現(xiàn)
遞歸實現(xiàn)是最難的,理由是遞歸本身很難理解。我認為遞歸的本質是通過不斷的改變參數(shù)找到問題的原點,再進行返回。邏輯處理部分則是在不斷找尋原點的過程中,或者是找到原點后在返回的過程中進行的。這個題目既可以在找原點的過程中設置邏輯處理,也可以在返還的過程中進行邏輯處理。
找原點的過程中設置邏輯處理:
public ListNode ReverseList(ListNode head) { //Reverse函數(shù)的兩個參數(shù)的意思是,當前節(jié)點和上一個節(jié)點 //head是原本函數(shù)的頭節(jié),null是更改后頭節(jié)點指向的值 return Reverse(head, null); } public ListNode Reverse(ListNode nowNode, ListNode lastNode) {、 //當前節(jié)點是null //說明上一個節(jié)點是最后一個節(jié)點 if (nowNode == null) { return lastNode; } //先保存下一個地址的位置 ListNode next = nowNode.next; //讓當前節(jié)點指向上一個節(jié)點 nowNode.next = lastNode; //處理完這個節(jié)點的邏輯之后開始前往下一個節(jié)點 return Reverse(next, nowNode); }
返還的過程中進行邏輯處理:
public ListNode ReverseList(ListNode head){ //當前節(jié)點的next元素沒有指向下一個元素的時候說明這是最后一個元素 if(head == null || head.next == null){ return head; } //找到最后一個元素,并開始一層一層的往上傳遞 ListNode last = ReverseList(head.next); //把下一個元素指向的元素改為自己 //(因為遞歸條件的影響當前的元素只可能是反轉后第二個元素之后的元素, // 所以head.next.next不會越界) head.next.next = head; //并且清除當前指向的節(jié)點,防止可能的問題(成環(huán)) head.next = null; //傳遞最后一個元素 return last; }
建議先看懂前面兩個方法再來看最后的遞歸,先看懂這個題目的基本處理邏輯。
后面兩個解法的本質是指針的運用,Java對這方面沒有很好的解釋,所以可能會有點難理解
總結
到此這篇關于java反轉鏈表的多種解決方法的文章就介紹到這了,更多相關java反轉鏈表解決方法內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Java SSH 秘鑰連接mysql數(shù)據(jù)庫的方法
這篇文章主要介紹了Java SSH 秘鑰連接mysql數(shù)據(jù)庫的方法,包括引入依賴的代碼和出現(xiàn)異常報錯問題,需要的朋友可以參考下2021-06-06Java使用Hutool+自定義注解實現(xiàn)數(shù)據(jù)脫敏
我們在使用手機銀行的時候經(jīng)常能看到APP上會將銀行卡的卡號中間部分給隱藏掉使用 ***** 來代替,在某些網(wǎng)站上查看一些業(yè)務密碼時(例如簽到密碼等)也會使用 ***** 來隱藏掉真正的密碼,那么這種方式是如何實現(xiàn)的呢,本文將給大家介紹使用Hutool+自定義注解實現(xiàn)數(shù)據(jù)脫敏2023-09-09Springboot啟動同時創(chuàng)建數(shù)據(jù)庫和表實現(xiàn)方法
這篇文章主要介紹了Springboot啟動同時創(chuàng)建數(shù)據(jù)庫和表,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習吧2023-01-01IntelliJ IDEA中出現(xiàn)"PSI and index do not match"錯誤的解決辦法
今天小編就為大家分享一篇關于IntelliJ IDEA中出現(xiàn)"PSI and index do not match"錯誤的解決辦法,小編覺得內容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2018-10-10