给定一个链表,删除链表的倒数第 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; } };
/** * struct ListNode { * int val; * struct ListNode *next; * }; */ class Solution { public: /** * * @param head ListNode类 * @param n int整型 * @return ListNode类 */ ListNode* removeNthFromEnd(ListNode* head, int n) { int count = 0; return removeNth(head, n, count); } ListNode* removeNth(ListNode* head, int n, int& count) { if (!head) return nullptr; head->next = removeNth(head->next, n, count); count++; if (count == n) return head->next; return head; } };
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; } }
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 p = head; ListNode q = p; int count = 1; //先判断只有一个节点的情况 if(p.next == null ){ return null; } //节点数大于1 else if(p.next != null){ //count为总共节点数 while(q.next!=null){ count++; q = q.next; } //删除的是否是第一个节点 if(n == count){ head = head.next; } //删除的不是第一个节点 else{ //p移动到要删除节点的前一个位置 for(int i = 1;i<count-n;i++){ p = p.next; } //删去节点 q = p.next; p.next = q.next; } } return head; } }非间隔指针的方法
/** * 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; } };