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

力扣题目
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

代码一
思路是两次遍历,第一次求得一共有多少结点,第二次遍历找到要删除结点的前一个位置,

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        int count = 0;
        ListNode p = new ListNode();
        p = head;
        //求得一共有多少结点
        while(p!=null){
            count++;
            p = p.next;
        }
        int i = 0;
        ListNode res = new ListNode();
        res.next = head;
        ListNode q = res;
        //找到要删除结点的前一个位置
        while(i<count-n){
            q = q.next;
            i++;
        }
        q.next = q.next.next;//删除目标节点
        return res.next;
    }
}

1.存储结点有一个技巧,那就是新建一个头结点res,让res.next指向head,同时让指针q指向res,操作时对q进行操作,那么有个好处,就是当第一个结点被删除时,res.next仍然能指向新链表的第一个结点,注意返回时要返回res.next,这在链表删除操作时很常用,题目203. 移除链表元素也用到了

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

例如,在本题中,如果我们要删除节点 yy,我们需要知道节点 yy 的前驱节点 xx,并将 xx 的指针指向 yy 的后继节点。但由于头节点不存在前驱节点,因此我们需要在删除头节点时进行特殊判断。但如果我们添加了哑节点,那么头节点的前驱节点就是哑节点本身,此时我们就只需要考虑通用的情况即可。

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/solution/shan-chu-lian-biao-de-dao-shu-di-nge-jie-dian-b-61/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。”

代码二
栈,先进栈,然后将n个结点出栈,这时当前栈顶也就是要删除结点的前驱结点。注意,也要添加哑节点并且进栈

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode res = new ListNode(0,head);
        ListNode cur = res;
        Deque<ListNode> stack = new LinkedList<ListNode>();
        while(cur!=null){
            stack.push(cur);
            cur = cur.next;
        }
        for(int i = 0;i<n;i++){
            stack.pop();
        }
        ListNode temp = stack.peek();
        temp.next = temp.next.next;
        return res.next;
    }
}

代码三
快慢指针,让两个指针相差n,当快指针为null时,慢指针就是我们要找的结点。也要设置哑节点。

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode res = new ListNode(0,head);
        ListNode slow = res;
        ListNode fast = head;
        //slow和fast实际上隔开了n+1个结点
        for(int i = 0;i<n;i++){
            fast = fast.next;
        }
        while(fast!=null){
            fast = fast.next;
            slow = slow.next;
        }
        //slow指向目标节点的前驱结点
        slow.next = slow.next.next;
        return res.next;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值