力扣第十九题(删除链表的倒数第N个结点)详解

该题要求删除倒数第n个结点,在不遍历整个链表的情况下, 可以考虑利用快慢指针,进行解答。同样也可以利用递归,当从后往前回溯到达倒数第n个数时,指针指向下一结点,从而删除倒数第n个结点。所有方法的核心思路是找到倒数第n个结点,然后上一结点的next指向下下一个结点,也就是下一节点的next,只不过实现的方法不同罢了。

方法一:双指针(快慢指针)

思路就是先让一个指针向前移动n个位置,再和让另一个指针和他一同移动,直到快指针到达链表的尾部。这时慢指针指向的就是倒数第n + 1个结点,这时将慢指针指向下一节点的next,即可删除倒数第n个结点。

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
       if(!head | !head -> next)return NULL;//判断链表是否为空
       ListNode *fast = head,*slow = head;//定义快慢指针
       for(int i = 0;i < n;i++){
           fast = fast -> next;
       }
       if(!fast)return head -> next;
       while(fast -> next){
           fast = fast -> next;
           slow = slow -> next;
       }
       slow -> next = slow -> next -> next;//删除结点
       return head;
    }
};

方法二:递归

先定义一个全局变量cur,以此来记录指针的移动,当cur等于n时,这时即到了倒数第n个结点。

class Solution {
public:
    int cur=0;
    ListNode* removeNthFromEnd(ListNode* head, int n) {
       if(!head) return NULL;
       head->next = removeNthFromEnd(head->next,n);
       cur++;
       if(n==cur) return head->next;
       return head;
    }
};

方法三:栈

创建一个哑结点指向链表的,可以省去对头结点的特殊判断,然后利用栈,将链表中的值一个一个的压入栈中,再弹出n个结点,这样栈里的头指针就是倒数第n个结点。

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* dummy = new ListNode(0, head);//创建一个带哑结点指针指向链表
        stack<ListNode*> stk;
        ListNode* cur = dummy;
        while (cur) {
            stk.push(cur);
            cur = cur->next;//进栈
        }
        for (int i = 0; i < n; ++i) {
            stk.pop(); //出n个结点
        }
        ListNode* prev = stk.top();
        prev->next = prev->next->next;//删除结点
        ListNode* ans = dummy->next;
        delete dummy;//删除哑结点
        return ans;
    }
};

方法四:计算链表长度

该方法较前面的简单一点,就是遍历链表,得到链表的长度,然后确定倒数第n个结点在链表中正着数的位置,再把指针定位到这个位置,完成删除操作。

class Solution {
public:
    int getLength(ListNode* head){
        int length = 0;
        while(head){
            head = head -> next;
            length++;
        }
        return length;
    }
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        if(!head |!head -> next)return NULL;//判断链表是否为空
        ListNode* dummy = head;
        int length = getLength(head);
        ListNode* cur = dummy;
        if(length - n == 0)return head -> next;//当删除的为头结点时,直接用head指向下一结点
        for(int i = 0;i < length - n - 1;i++){
            cur = cur -> next;
        }
        cur -> next = cur -> next -> next;
        ListNode* ans = dummy ;
        return ans;
    }
};

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值