查找單鏈表中倒數第k個節點。
思路:
1.編寫一個方法,接收head節點,同時接收一個x
2.x表示是倒數第x個節點
3.先把鏈表從頭到尾遍歷,得到鏈表總長度
4.得到總長度後,我們從鏈表的第一個開始遍歷(總長度-x)個,就可以得到我們需要的節點
public static void main(String[] args){
SingleLinkedListManger sllm = new SingleLinkedListManger();
System.out.println(getLength(sllm.getHead()));
}
/**
* 查找單鏈表中的倒數第k個節點
* 思路
* 1.編寫一個方法,接受head節點,同時接收一個index
* 2.index表示是倒數第index個節點
* 3.先把鏈表從頭到尾遍歷,得到鏈表的總的長度getLength
* 4.得到size後,我們從鏈表的第一個開始遍歷(size-index)個,就可以得到
* 5.如果找到了,則返回該節點,否則返回null
* @param head
* @param index
* @return
*/
public static HeroNode findLastIndexNode(CharacterNode head,int x){
if (head.next == null){
return null;
}
//第一次遍歷 獲取鏈表長度(節點個數)
int size = getLength(head);
//第二次遍歷 獲取size - index位置,就是我們倒數的第k個節點
//先做一個index的校驗
if (x <= 0 || x > size){
return null;
}
//定義一個輔助變量,for循環定位到倒數的index
CharacterNode cur = head.next;
for (int i = 0; i < size-x; i++) {
cur =cur.next;
}
return cur;
}
public static int getLength(CharacterNode head){
if (head.next == null){
return 0;
}
int length = 0;
CharacterNode cur = head.next;
while (cur != null){
length++;
cur = cur.next;
}
return length;
}
class SingleLinkedListManger{
/**
* 先初始化一個頭節點,頭節點不要動,不存放具體數據
*/
private HeroNode head = new HeroNode(0,"","");
public HeroNode getHead(){
return head;
}
}
class CharacterNode{
public int id;
public String name;
public String nickname;
public CharacterNode next;
public CharacterNode pre;
public CharacterNode(int id,String name,String nickname){
this.id = id;
this.name = name;
this.nickname = nickname;
}
@Override
public String toString() {
return "CharacterNode{" +
"id=" + id +
", name='" + name + '\'' +
", nickname='" + nickname + '\'' +
'}';
}
}
單鏈表的反轉
思路:
定義一個新的節點reverseHead=new CharacterNode();然後從頭到尾遍歷原來的鏈表,每遍歷一個節點,就將其取出,放在新的鏈表reverseHead的最前端,最後將原來鏈表的頭節點的next指向reverseHead的next實現反轉。
public static void reverseList(CharacterNode head){
//如果但前鏈表爲空,或者只有一個節點,無需反轉,直接返回
if (head.next == null || head.next.next == null){
return;
}
CharacterNode cur = head.next;
CharacterNode next = null;
CharacterNode reverseHead = new CharacterNode(0,"","");
/**
* 遍歷原來的鏈表,每遍歷一個節點,就將將其取出,並放在新的鏈表reverseHead的最前端
*/
while (cur != null){
//先暫時保存當前節點的下一個節點,因爲後面需要使用
next = cur.next;
//將cur的下一個節點指向新的鏈表的最前端
cur.next =reverseHead.next;
//將cur連接到新的鏈表上
reverseHead.next = cur;
//讓cur後移
cur = next;
}
head.next =reverseHead.next;
}
單鏈表逆序
逆序和反轉的區別是,逆序是在不該改變鏈表的結構的條件下進行輸出。這種情況下我們可以使用棧這個數據結構,將各個節點壓入到棧中,然後利用棧的先進後出的特點,就實現了逆序打印的效果。
public static void reversePrint(HeroNode head){
if (head.next == null){
return;
}
//創建一個棧,將各個節點壓入棧
Stack<HeroNode> stack = new Stack<HeroNode>();
HeroNode cur = head.next;
//將鏈表的所有節點壓入棧
while (cur != null){
stack.push(cur);
//將cur後移 這樣就可以豔如下一個節點
cur = cur.next;
}
/**
* 出棧
*/
while (stack.size() > 0){
System.out.println(stack.pop());
}
}
合併兩個有序的單鏈表,合併之後依然有序。
思路:創建一個新的節點,對兩個鏈表的數據進行比較,按照順序插入。
class ListNode{
int val;
ListNode next;
ListNode(int x){
val = x;
}
}
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if (l1 == null) return l2;
if (l2 == null) return l1;
ListNode head = null;
if (l1.val <= l2.val){
head = l1;
head.next = mergeTwoLists(l1.next, l2);
} else {
head = l2;
head.next = mergeTwoLists(l1, l2.next);
}
return head;
}