leetcode19_删除链表的倒数第N个节点_链表_双指针_递归

20 篇文章 0 订阅
10 篇文章 0 订阅

1. 最简单的想法就是先求出链表的长度len,再找到(len-k)个节点,即删除节点的前一个节点,就可以将其删除.

2. 两次遍历.

/**
 * 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==NULL) return head;
        ListNode* tmp = head;
        int count = 0;
        //求链表长度.注意
        //不要用head求,会改变head,另外指定tmp.
        while(tmp!=NULL) {
            tmp = tmp->next;
            count++;
        }
        //哑结点消除删除只剩一个节点情况,以及删除第一个节点的情况
        //的边界条件.
        ListNode* dummy = new ListNode(0);
        dummy->next = head;
        tmp = dummy;
        int c = 0;
        while(c!=count-n) {
            tmp = tmp->next;
            c++;
        }
        //找到了就停止.
        tmp->next = tmp->next->next;
        //返回哑结点的后一个节点.
        return dummy->next;
    } 
};

3. 一次遍历

4. 可以优化为只使用一次遍历.使用双指针.快慢指针,快指针先走n-2,然后快慢指针一起走,这样快慢指针的间隔保持恒定的间隔,即可以求得其倒数第n个节点前一个节点,便可以将倒数第n个节点删除了.

5. 快慢指针找到倒数第N个节点.

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        if(head==NULL) return head;
        ListNode* dummy = new ListNode(0);
        //哑结点消除边界情况,比如只剩一个数,
        //或者删除第一个节点.
        dummy->next = head;
        ListNode* slow = dummy;
        ListNode* fast = dummy;
        //使快慢指针的间隔为n.
        for(int i=1;i<=n;i++) {
            fast = fast->next;
        }
        //这样当快指针走到末尾时,慢指针
        //就是倒数第N个节点.
        while(fast->next!=NULL) {
            slow = slow->next;
            fast = fast->next;
        }
        slow->next = slow->next->next;
        return dummy->next;

    } 
};

三. 递归方法

1. 递归方法分为递和归两个过程.

2. 递归不好理解的时候可以具体举几个简单的例子, 比如[1],1即一个数的情况.

class Solution {
public:
    int i=0;
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        //先是递的过程,如果找到最后一个节点,直接返回NULL;
        if(head==NULL) return NULL;
        //当前指针下一个指针是哪个.
        head->next = removeNthFromEnd(head->next,n);
        //归的时候统计当前是第几个指针.
        i++;
        //如果是待删除指针,返回当前指针下一个
        //否则返回head.
        if(i==n) return head->next;
        else return head;
    } 
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值