- LeetCode(Java版)19. 刪除鏈表的倒數第N個節點
解法1:不需要去遍歷兩次,一次即可,思路是,用兩個指針p,q先指向頭節點,讓q指針走到第n個位置,然後兩個指針同時往後走,走到q.next==null是說明p已經到達倒數第n個節點的前面的那個節點,此時刪除下一個節點即可。
注意:當刪除頭節點和只有一個元素的情況。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
if(head==null)
return head;
ListNode p = head;
ListNode q =head;
//用count記錄走了多少步,和最終鏈表的長度
int count=0;
while(q.next!=null){
count++;
//前n步只讓q指針走
if(count<=n){
q=q.next;
}else{
q=q.next;
p=p.next;
}
}
//循環結束時p到達了倒數n個元素的前面一個元素
//兩個特殊情況,即鏈表只有一個元素和要刪除的爲頭節點的情況
if(head.next==null || count+1 == n){
head=head.next;
}else{
p.next=p.next.next;
}
return head;
}
}
以下是對應的 Kotlin 版本
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
internal class Solution {
fun removeNthFromEnd(head: ListNode?, n: Int): ListNode? {
var head: ListNode? = head
if (head == null) return head
var p: ListNode = head
var q: ListNode = head
//用count記錄走了多少步,和最終鏈表的長度
var count = 0
while (q.next != null) {
count++
//前n步只讓q指針走
if (count <= n) {
q = q.next
} else {
q = q.next
p = p.next
}
}
//循環結束時p到達了倒數n個元素的前面一個元素
//兩個特殊情況,即鏈表只有一個元素和要刪除的爲頭節點的情況
if (head.next == null || count + 1 == n) {
head = head.next
} else {
p.next = p.next.next
}
return head
}
}
參考 https://blog.csdn.net/weixin_39043567/article/details/89813993
- 輸入一個鏈表,按鏈表從尾到頭的順序返回一個ArrayList。
import java.util.Stack;
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
Stack<Integer> stack = new Stack<>();
while (listNode != null) {
stack.push(listNode.val);
listNode = listNode.next;
}
ArrayList<Integer> list = new ArrayList<>();
while (!stack.isEmpty()) {
list.add(stack.pop());
}
return list;
}
}
- 輸入一個鏈表,反轉鏈表後,輸出新鏈表的表頭。
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
public class Solution {
public ListNode ReverseList(ListNode head) {
if(head==null)
return null;
//head爲當前節點,如果當前節點爲空的話,那就什麼也不做,直接返回null;
ListNode pre = null;
ListNode next = null;
//當前節點是head,pre爲當前節點的前一節點,next爲當前節點的下一節點
//需要pre和next的目的是讓當前節點從pre->head->next1->next2變成pre<-head next1->next2
//即pre讓節點可以反轉所指方向,但反轉之後如果不用next節點保存next1節點的話,此單鏈表就此斷開了
//所以需要用到pre和next兩個節點
//1->2->3->4->5
//1<-2<-3 4->5
while(head!=null){
//做循環,如果當前節點不爲空的話,始終執行此循環,此循環的目的就是讓當前節點從指向next到指向pre
//如此就可以做到反轉鏈表的效果
//先用next保存head的下一個節點的信息,保證單鏈表不會因爲失去head節點的原next節點而就此斷裂
next = head.next;
//保存完next,就可以讓head從指向next變成指向pre了,代碼如下
head.next = pre;
//head指向pre後,就繼續依次反轉下一個節點
//讓pre,head,next依次向後移動一個節點,繼續下一次的指針反轉
pre = head;
head = next;
}
//如果head爲null的時候,pre就爲最後一個節點了,但是鏈表已經反轉完畢,pre就是反轉後鏈表的第一個節點
//直接輸出pre就是我們想要得到的反轉後的鏈表
return pre;
}
}
- 輸入一個鏈表,輸出該鏈表中倒數第k個結點。
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
public class Solution {
public ListNode FindKthToTail(ListNode list,int k) {
if (list == null) return list;
ListNode node = list;
int count = 0;
while (node != null) {
count++;
node = node.next;
}
if (count < k) return null;
ListNode p = list;
for (int i = 0; i < count - k; i++) {
p = p.next;
}
return p;
}
}