C++进阶练习删除链表的倒数第N个结点详解

 

1.链接

19. 删除链表的倒数第 N 个结点.

 

2.题目描述

 

3.解题思路

方法一

1.在对链表进行操作时,一种常用的技巧是添加一个哑节点(dummy node),它的 next指针指向链表的头节点。这样一来,我们就不需要对头节点进行特殊的判断了。

例如,在本题中,如果我们要删除节点 y,我们需要知道节点 y 的前驱节点 x,并将 x 的指针指向 y 的后继节点。

但由于头节点不存在前驱节点,因此我们需要在删除头节点时进行特殊判断。但如果我们添加了哑节点,那么头节点的前驱节点就是哑节点本身,此时我们就只需要考虑通用的情况即可。特别地,在某些语言中,由于需要自行对内存进行管理。因此在实际的面试中,对于「是否需要释放被删除节点对应的空间」这一问题,我们需要和面试官进行积极的沟通以达成一致。下面的代码中默认不释放空间。

一种容易想到的方法是,我们首先从头节点开始对链表进行一次遍历,得到链表的长度 L。随后我们再从头节点开始对链表进行一次遍历,当遍历到第 L−n+1 个节点时,它就是我们需要删除的节点。为了方便删除操作,我们可以从哑节点开始遍历 L−n+1 个节点。当遍历到第 L−n+1 个节点时,它的下一个节点就是我们需要删除的节点,这样我们只需要修改一次指针,就能完成删除操作。

方法二

我们可以设想假设设定了双指针 p 和 q 的话,当 q 指向末尾的 NULL,p 与 q 之间相隔的元素个数为 n 时,那么删除掉 p 的下一个指针就完成了要求。

设置虚拟节点 dummyHead 指向 head

设定双指针 p 和 q,初始都指向虚拟节点 dummyHead

移动 q,直到 p 与 q 之间相隔的元素个数为 n

同时移动 p 与 q,直到 q 指向的为 NULL

将 p 的下一个节点指向下下个节点

 

4.题解

方法一

/**
* 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:
  int getLength(ListNode* head) {
      int length = 0;
      while (head) {
          ++length;
          head = head->next;
      }
      return length;
  }
  ListNode* removeNthFromEnd(ListNode* head, int n) {
      ListNode* dummy = new ListNode(0, head);
      int length = getLength(head);
      ListNode* cur = dummy;
      for (int i = 1; i < length - n + 1; ++i) {
          cur = cur->next;
      }
      cur->next = cur->next->next;
      ListNode* ans = dummy->next;
      delete dummy;
      return ans;
  }
};

方法二

/**
* 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* dummyHead = new ListNode(0);
      dummyHead->next = head;

      ListNode* p = dummyHead;
      ListNode* q = dummyHead;
      for( int i = 0 ; i < n + 1 ; i ++ ){
          q = q->next;
      }
      while(q){
          p = p->next;
          q = q->next;
      }
      ListNode* delNode = p->next;
      p->next = delNode->next;
      delete delNode;
      ListNode* retNode = dummyHead->next;
      delete dummyHead;
      return retNode;
  }
};

关于C++进阶练习删除链表的倒数第N个结点详解的文章就介绍至此,更多相关C++删除链表节点内容请搜索编程宝库以前的文章,希望以后支持编程宝库

 1.问题来源要用SQLite数据库去保存一段定长的char型数组,里面可能有\0等字符,所以当作字符串varchar处理铁定丢失数据,所以要用二进制保存BL ...