LeetCode-Remove Nth Node From End of List的一种算法

本文介绍了一种解决LeetCode中删除链表倒数第n个节点问题的算法。通过两种方法实现:一种是一般算法,计算链表长度后再定位删除;另一种是高效算法,使用双指针遍历,一次遍历完成删除操作。文章详细解析了每种方法的步骤和代码实现。

LeetCode-Remove Nth Node From End of List的一种算法

题目链接:https://leetcode.com/problems/remove-nth-node-from-end-of-list/description/

Given a linked list, remove the n-th node from the end of list and return its head.

Example:
Given linked list: 1->2->3->4->5, and n = 2.
After removing the second node from the end, the linked list becomes 1->2->3->5.

Note:
Given n will always be valid.

由题意可知,本次题目要求我们删除链表的倒数第n个节点,一般思路就是得到节点长度,然后减去n-1,找到删去节点的位置,在将其删去即可。
需要注意的是该节点可能是第一个节点,也可能是最后一个节点,这时操作又会有所不同。
于是这次也给出一个更加高效的算法,通过同时使用两个指针遍历链表,两个指针相差n个节点,如此一来当先遍历的节点遍历完整个链表,后遍历的节点就会指向倒数第n个节点。

一般算法如下:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        if (head->next == NULL) {			//判断只有一个节点的情况
            return n==1?NULL:head;
        }
        ListNode* l = head, *l1 = head, *l2 = head->next;
        int i = 0;
        while (l->next != NULL) {			//计算从头结点和尾节点的间隔
            l = l->next;
            i++;							//当有5个节点时,i为4;
        }
        int flag = i-n;						//判断删除的是否是头结点的标志
        l = l1;
        //遍历到待删除的节点,l2指向该结点,l1指向上一节点
        for (int j = 0; j < i-n; j++) {
            l1 = l1->next;
            l2 = l2->next;
        }
        //当flag=-1,代表i+1=n,而i+1又为整个链表长度,故此时要删除的是头结点
        if (flag == -1) {
            return l2;		//由于此时i-n=-1,没有进行上面的for循环,l2指向第二节点
        }
        //当l2既不指向是头结点,也不指向尾节点时的删减操作
        if (l2->next != NULL) {
            l2 = l2->next;
            delete l1->next;
            l1->next = l2;
            return l;
        }
        //当l2是尾节点时的删减操作。
        else {
            delete l2;
            l1->next = NULL;
            return l;
        }
    }
};

高效算法如下:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode *l = head, *l1 = head, *l2 = head, *temp;
        //先让l2进行n次遍历
        while (n > 0) {
            l2 = l2->next;
            n--;
        }
        //若此时l2为空,即l2指向尾节点的next的空节点,此时判断出删除的是头结点
        if (l2 == NULL) {
            return l->next;
        }
        //若非删除头结点,则开始令第二个指针l1与l2同时遍历
        while(l2 != NULL) {
            temp = l1;		//temp指向l1的上一节点
            l1 = l1->next;	//l1指向待删除节点
            l2 = l2->next;
        }
        //进行删除操作
        temp->next = l1->next;
        l1->next = NULL;
        return l;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值