给定一个链表,删除链表的倒数第 n 个节点并返回链表的头指针
例如,
例如,
给出的链表为:
,
.
删除了链表的倒数第
个节点之后,链表变为
.
删除了链表的倒数第
数据范围: 链表长度
,链表中任意节点的值满足
要求:空间复杂度
,时间复杂度 )
备注:
备注:
题目保证
一定是有效的
import java.util.*;
/*
* public class ListNode {
* int val;
* ListNode next = null;
* }
*/
public class Solution {
/**
*
* @param head ListNode类
* @param n int整型
* @return ListNode类
*/
public ListNode removeNthFromEnd (ListNode head, int n) {
// write code here
//需要设置一个虚拟节点
ListNode v = new ListNode(-1);
//虚拟节点指向头结点
v.next = head;
//使用双指针的方案
ListNode last = head;
ListNode nodeN = v;
int index = 1;
while(last != null){
last = last.next;
if(index > n) nodeN = nodeN.next;
index ++;
}
//执行删除操作
ListNode temp = nodeN.next;
nodeN.next = temp.next;
return v.next;
}
} /**
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
class Solution {
public:
/**
*
* @param head ListNode类
* @param n int整型
* @return ListNode类
*/
ListNode* removeNthFromEnd(ListNode* head, int n) {
// write code here
ListNode *dummy_head = new ListNode(-1);
dummy_head->next = head;
ListNode *fast=head, *slow=dummy_head;
while(n) {
fast = fast->next;
--n;
}
while(fast) {
fast = fast->next;
slow = slow->next;
}
slow->next = slow->next->next;
return dummy_head->next;
}
};
func removeNthFromEnd( head *ListNode , n int ) *ListNode {
// write code here
var (
fast *ListNode = head
slow *ListNode = head
pre *ListNode
)
// if n <=0 {
// return head
// }
for i:= 0 ; i < n-1 ; i++{
fast = fast.Next
// if fast.Next == nil{
// break
// }
}
for fast.Next != nil {
pre = slow
slow = slow.Next
fast = fast.Next
}
if pre == nil {
return head.Next
}else{
pre.Next = slow.Next
}
return head
}
//就是一个走到n位置,另一个和他一起走,那么就倒数了
public ListNode removeNthFromEnd (ListNode head, int n) {
ListNode node=head;
ListNode fast=head;
int count=0;
while (count<n){
fast= fast.next;
if(fast==null) return head.next;
count++;
}
while (fast.next!=null){
fast=fast.next;
node=node.next;
}
node.next=node.next.next;
return head;
} function removeNthFromEnd( head , n ) {
// write code here
const map = new Map()
let cur = head
let i = 0
while (cur) {
map.set(i, cur)
i ++
cur = cur.next
}
const pre = map.get(i - n - 1)
const next = map.get(i - n + 1)
if (!pre) return head.next
pre.next = next
return head
} import java.util.*;
/*
* public class ListNode {
* int val;
* ListNode next = null;
* }
*/
public class Solution {
/**
*
* @param head ListNode类
* @param n int整型
* @return ListNode类
*/
public ListNode removeNthFromEnd (ListNode head, int n) {
// write code here
ListNode cur=head;
ListNode fast=head;
for(int i=0;i<n;i++){
fast=fast.next;
if(fast==null) return head.next;
}
while(fast.next!=null){
cur=cur.next;
fast=fast.next;
}
cur.next=cur.next.next;
return head;
}
} ListNode* removeNthFromEnd(ListNode* head, int n) {
int i, length = 0;
struct ListNode* L; //返回表
struct ListNode* c; //用于遍历链表求表长
struct ListNode* pre; //工作指针前驱
struct ListNode* p; //工作指针
struct ListNode* q; //释放被删节点
if(head == NULL || head->next == NULL){ //表为空或仅有1个结点,必然返回空表
return NULL;
}else {
pre = head;
c = head;
L = head;
p = head->next;
while(c != NULL){
length++; //求表长
c = c->next;
}
if(n == length){ //删除首节点,
q = pre;
L = L->next;
free(q);
return L;
}else{ //删除非首节点
for(i = 1; i < length - n; i++) //将p指向需删结点,pre作为前驱跟随
{
pre = pre->next;
p = p->next;
}
if(p->next == NULL){ //若为尾节点,直接将pre指针域置空
q = p;
pre->next = NULL;
free(q);
}else{ //非尾节点普通删除方法
q = p;
p = p->next;
pre->next = p;
free(q);
}
}
}
return L;
} ListNode* removeNthFromEnd(ListNode* head, int n) {
// write code here
if(NULL == head || n <= 0)
return NULL;
ListNode* first = head;
ListNode* last = head;
for(int i=1; i < n ;i++)
{
last = last->next;
if(last == NULL)
return NULL;
}
//链表长度就为n,删除首结点
if(last->next == NULL)
{
//占存不用的结点,好释放
ListNode* temp = head->next;
delete(head);
return temp;
}
//last往后移动一个单位这样下一次first就可以少移动一个
last = last->next;
//如果链表长度>n
while(last->next != NULL)
{
last = last->next;
first = first->next;
}
//占存结点并释放。不能直接释放first->last,会出错的的。
ListNode* temp = first->next;
first->next = first->next->next;
delete(temp);
return head;
}
class Solution {
public:
/**
*
* @param head ListNode类
* @param n int整型
* @return ListNode类
*/
ListNode* removeNthFromEnd(ListNode* head, int n) {
if (nullptr == head) return nullptr;
if (0 == n) return head;
ListNode *dummy = new ListNode(0);
dummy->next= head;
int deleteIndex = sizeOfLinkedListWithListNode(head) - n;
ListNode*cur = dummy;
for (int i=1; i<= deleteIndex ;++i) {
cur = cur->next;
}
cur->next = cur->next->next;
ListNode* ans = dummy->next;
return ans;
}
int sizeOfLinkedListWithListNode(ListNode* head) {
if(nullptr == head) return 0;
ListNode* cur = head;
int size = 0;
while(cur) {
size++;
cur = cur->next;
}
return size;
}
}; class Solution {
public:
/**
*
* @param head ListNode类
* @param n int整型
* @return ListNode类
*/
ListNode* removeNthFromEnd(ListNode* head, int n) {
// write code here
int len_List = 0;
map<int, ListNode*> index_node;
ListNode* temp = head;
while (temp != NULL) //放进map里,长度查询好了
{
index_node[len_List + 1] = temp;
len_List++;
temp = temp->next;
}
if (n == len_List) //如果是第一位
return head->next;
int index = len_List - n; //查询正确的map位置
temp = index_node[index];
temp->next = temp->next->next;
return head;
}
}; ListNode* removeNthFromEnd(ListNode* head, int n) {
// write code here
ListNode *pos=head;
ListNode *prev=NULL;
ListNode *res=head;
while(n--)
{
pos=pos->next;
}
while(pos)
{
prev=res;
res=res->next;
pos=pos->next;
}
if(prev==NULL) return res->next;
prev->next=res->next;
return head;
} 简洁的快慢指针法 整体思路并不复杂,使用双指针标记即可,
难点在于要理清楚,距离和循环边界条件
及注意特殊情况,删除头节点时的处理
import java.util.*;
/*
* public class ListNode {
* int val;
* ListNode next = null;
* }
*/
public class Solution {
/**
*
* @param head ListNode类
* @param n int整型
* @return ListNode类
*/
public ListNode removeNthFromEnd (ListNode head, int n) {
// write code here
if(head==null){
return null;
}
//新 new 一个节点指向头节点,为待删节点前一个节点
ListNode preNeedDel=new ListNode(0);
preNeedDel.next=head;
//标记需要删除的节点
ListNode needDel=head;
//标识最后一个节点
ListNode end=head;
//标识删除的倒数第 n 个节点
int i=0;
while(end!=null){
//先拉开 n 个距离 注意这里 end 会走到 null
if(i<n){
end=end.next;
i++;
}else{
end=end.next;
preNeedDel=preNeedDel.next;
needDel=needDel.next;
}
}
preNeedDel.next=preNeedDel.next.next;
//注意删除头节点情况
if(needDel==head){
return preNeedDel.next;
}
return head;
}
}
import java.util.*;
/*
* public class ListNode {
* int val;
* ListNode next = null;
* }
*/
public class Solution {
/**
*
* @param head ListNode类
* @param n int整型
* @return ListNode类
*/
public ListNode removeNthFromEnd (ListNode head, int n) {
ListNode root = new ListNode(-1);
root.next = head;
// 方便处理头节点的删除
ListNode pi = root, pk = root;
// 先使 pi 前进 n 步,确保 pk 和 pi 相差 (n),当 pi 走到末尾的时候,pk 就是倒数第 n + 1 个节点,直接删除pk后面的节点即可
for(int i = 0; i < n; i++) {
pi = pi.next;
}
while(pi.next != null) {
pi = pi.next;
pk = pk.next;
}
// 删除 pk 后面的节点
pk.next = pk.next.next;
return root.next;
}
} /**
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
class Solution {
public:
/**
*
* @param head ListNode类
* @param n int整型
* @return ListNode类
*/
ListNode* removeNthFromEnd(ListNode* head, int n) {
// 为了防止是删除第一个节点 所以增加一个新的节点指向头结点
ListNode* hh = new ListNode(-1);
hh->next = head;
int len = 0;
ListNode* pre = head;
while(pre != nullptr)
{
len++;
pre = pre->next;
}
// 得到删除节点的前一个节点的位置
int erase_idx = len - n;
if(len == 1) return nullptr;
pre = hh;
// 移动到删除节点的头一个节点的位置
for(int i = 0; i < erase_idx; i++) pre = pre->next;
// 进行删除操作
pre->next = pre->next->next;
//返回值
return hh->next;
}
}; ListNode* removeNthFromEnd(ListNode* head, int n) {
if(head == nullptr || n < 1) return NULL;
ListNode *newHead = new ListNode(-1);
newHead->next = head;
ListNode *front = newHead, *pre = NULL, *cur = newHead;
while (n--)
front = front->next;
while (front) {
front = front->next;
pre = cur;
cur = cur->next;
}
if(cur->next)
pre->next = cur->next;
else
pre->next = NULL;
return newHead->next;
}