リンク リストが与えられた場合、リンク リストの最後の n 番目のノードを削除し、リンク リストの先頭ノードを返します。
例 1:
入力: head = [1,2,3,4,5]、n = 2
出力: [1,2,3,5]
例 2:
入力: head = [1]、n = 1
出力: []
例 3:
入力: head = [1,2]、n = 1
出力: [1]
ヒント:
リンク リスト内のノード数は sz
1 <= sz <= 30
0 <= Node.val <= 100
1 <= n <= sz
高度: シングル パス スキャンで実装するのが最適です。
アイデア:
ダブル ポインターを使用して、1 回だけトラバースします。
従来の考え方は、リンクされたリスト内のノードの総数を取得するために一度トラバースし、n の値に従って削除する前のノードを見つけるためにトラバースし、前のノードの次のポインターを操作することです。
高速ポインターと低速ポインターを使用すると、高速ポインターを最初に n ステップ移動させることができます. 高速ポインターが削除するノードに到達すると、高速ポインターと低速ポインターが同時に前方に移動し、次のノードを指します.ポインタが最後のノードに到達し、判定条件が fast->next==NULL である場合、ループを抜け、slow ポインタの位置が削除するノードの前の位置になります。
もちろん、特別な状況も考慮する必要があります. たとえば、ノードが 1 つしかない場合は NULL を返します. 最初のノードを削除する場合は、最後の高速ポインタが最後のノードの次のノード、つまり NULL を指す必要があります。 .
コード:
C++
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode *slow=head,*fast=head;
if(!head&&!head->next)
return NULL;
for(int i=0;i<n;++i)
fast=fast->next;
if(!fast)
return head->next;
while(fast->next){
//用fast->next判断是不是最后一个结点
slow=slow->next;
fast=fast->next;
}
slow->next=slow->next->next;
return head;
}
};
ジャワ
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
if(head==null&&head.next==null)
return null;
ListNode slow=head,fast=head;
for(int i=0;i<n;++i)
fast=fast.next;
if(fast==null)
return head.next;
while(fast.next!=null){
slow=slow.next;
fast=fast.next;
}
slow.next=slow.next.next;
return head;
}
}