LintCode 174.删除链表中倒数第n个节点

题目描述

思路
结合前面一题的思路即可

/**
 * Definition of singly-linked-list:
 * class ListNode {
 * public:
 *     int val;
 *     ListNode *next;
 *     ListNode(int val) {
 *        this->val = val;
 *        this->next = NULL;
 *     }
 * }
 */

class Solution {
public:
    /**
     * @param head: The first node of linked list.
     * @param n: An integer
     * @return: The head of linked list.
     */
    ListNode * removeNthFromEnd(ListNode * head, int n) {
        // write your code here
        if(head == NULL || head->next==NULL)
        {
            return NULL;
        }
        
        ListNode *p = head;
        int numNode = 0;
        while(p != NULL)
        {
            numNode++;
            p = p->next;
        }
        int numDelete = numNode-n;  //找到待删节点的前一个节点
        p = head;
        if(numDelete <= 0)    //要删除第一个节点
        {
            p = p->next;
            return p;
        }
        while(--numDelete)
        {
            p = p->next;
        }
        p->next = p->next->next;
        return head;
    }
};

但是提交的过程中发现了好多坑

  1. 只有一个元素
  2. 有两个元素
  3. 待删除的节点为头结点
    以上种种情况的特殊处理

参考程序

/**
* 本参考程序来自九章算法,由 @九章算法 提供。版权所有,转发请注明出处。
* - 九章算法致力于帮助更多中国人找到好的工作,教师团队均来自硅谷和国内的一线大公司在职工程师。
* - 现有的面试培训课程包括:九章算法班,系统设计班,算法强化班,Java入门与基础算法班,Android 项目实战班,
* - Big Data 项目实战班,算法面试高频题班, 动态规划专题班
* - 更多详情请见官方网站:http://www.jiuzhang.com/?source=code
*/ 

class Solution {
public:
    /*
    题意:删除链表中倒数第n个结点,尽量只扫描一遍。
    使用两个指针扫描,当第一个指针扫描到第N个结点后,
    第二个指针从表头与第一个指针同时向后移动,
    当第一个指针指向空节点时,另一个指针就指向倒数第n个结点了
    */
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode *res = new ListNode(0);
        res->next = head;
        ListNode *tmp = res;
        for (int i = 0; i < n; i++) {
            head = head->next;
        }
        while (head != NULL) {
            head = head->next;
            tmp = tmp->next;
        }
        tmp->next = tmp->next->next;
        return res->next;
    }
};
删除链表倒数第 N 个节点可以通过以下两种方法实现: ### 方法一:两次遍历法 先统计链表的总节点数,再计算出要删除节点是正数第几个,最后进行删除操作。 - 设两个指针同时指向链表的第一个节点,一个指针遍历链表统计出总共有多少个节点记为 `i`,用总数减去 `N`,即可以算出要删除节点为正数第几个节点记为 `index = i - N`,让另一个指针移动到 `index` 节点的前一个节点(如果要删除节点不是第一个节点)。 - 最后执行删除操作,如果要删除节点为第一个节点,则需要修改头指针,反之,则直接删除即可 [^1]。 以下是 Java 代码示例: ```java /** * 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) { int j; // 删除的是正数第 j 个结点 int k = 1; int i = 0; // 统计结点总数 if (head == null) { return head; } ListNode list1 = head; while (list1 != null) { i++; list1 = list1.next; } if (n == i) { head = head.next; return head; } if (i == 1) { return null; } j = i - n + 1; list1 = head; while (k < j - 1) { list1 = list1.next; k++; } if (n == 1) { list1.next = null; return head; } list1.next = list1.next.next; return head; } } ``` ### 方法二:快慢指针法 利用快慢指针,让 `slow` 指针指向第一个节点,让 `fast` 指针和 `slow` 间隔 `N` 个节点,即指向第 `N` 个节点。然后同时移动 `slow` 和 `fast`,每次前进一步,直到 `fast` 指针到最后一个指针,此时 `slow` 指针就是倒数第 `N` 个节点。找到第 `N` 个节点之后需要删除掉这个节点,因为是单链表,必须保留被删除节点之前的这个节点,以及被删除节点之后的那个节点,接着桥接上前后的节点 [^3]。 以下是 Python 代码示例: ```python # 定义链表节点类 class ListNode: def __init__(self, val=0, next=None): self.val = val self.next = next def removeNthFromEnd(head, n): dummy = ListNode(0) dummy.next = head slow = dummy fast = dummy # 让 fast 指针先移动 n 步 for _ in range(n + 1): fast = fast.next # 同时移动 slow 和 fast 指针 while fast: slow = slow.next fast = fast.next # 删除倒数第 n 个节点 slow.next = slow.next.next return dummy.next ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值